2

私は、DAL が IDataReader、オブジェクト (int、string など)、または DataSet を返す関数を持つ基本クラスで構成されるプロジェクトに割り当てられました。ExecuteNonQuery 関数も存在します。この DAL は USP (SQL Server) にのみアクセスし、MS の SqlHelper を使用してクエリを実行しています。ベースからの 2 つのサンプル関数を次に示します。

    protected IDataReader ExecuteReader(string storedProcedure, params object[] parameterValues)
    {
        SqlConnection HConnection = new SqlConnection(myConnString);
        IDataReader ret = null;
        try
        {
            ret = SqlHelper.ExecuteReader(HConnection, storedProcedure, parameterValues);
        }
        catch (Exception ex)
        {
            HanldeError(ex, storedProcedure, parameterValues);
        }
        return ret;
    }

    protected object ExecuteScalar(string storedProcedure, params object[] parameterValues)
    {
        using (SqlConnection HConnection = new SqlConnection(myConnString))
        {
            object ret = null;
            try
            {
                ret = SqlHelper.ExecuteScalar(HConnection, storedProcedure, parameterValues);
            }
            catch (Exception ex)
            {
                HanldeError(ex, storedProcedure, parameterValues);
            }
            return ret;
        }
    }

他のクラスはこの基本クラスから派生し、タスク固有の DAL クラスを作成します。たとえば、次のとおりです。

public class Orders : BaseDal {
    public IDataReader GetOrdersList(int clientId, int agentId)
    {
        return ExecuteReader("usp_Orders_GetOrdersList", clientId, agentId);
    }
    ...
}

次に、DAL 関数を呼び出し、IDataReader オブジェクトから読み取ったデータに基づいてデータをオブジェクト (Order オブジェクトなど) に入力する BLL クラスがあります。

    public Order[] GetOrdersList(int ClientIDX, int AgentIDX)
    {
        List<Order> ret = null;
        using (IDataReader dr = objDAL.GetOrdersList(ClientIDX, AgentIDX))
        {
            if (dr != null)
            {
                ret = new List<Order>();
                while (dr.Read())
                {
                    ret.Add(xReadOrder(dr, 0));
                }
            }
        }
        return ret.ToArray();
    }

私の質問はこれです-BaseDalから取得したコードを見ると、ExecuteScalarだけが実際にSqlConnectionオブジェクト(usingステートメント)を終了することに気付くでしょう-これはそこにあるすべての関数の場合です. ExecuteReader では、開いている SqlDataReader オブジェクトを返し、接続を閉じるとリーダーが無効になるため、これを行うことはできません。DAL から IDataReader を取得して使用するすべてのコードで using ステートメントを使用していますが、SqlConnection オブジェクトも破棄されていますか、それとも後の段階で GC されており、すぐに解放しないことで接続プールが損なわれています? もしそうなら、これはどのように治療することができますか?

また、上記の方法よりも DAL を作成するためのより良い方法はありますか? データ ストアにとらわれない DAL についてはあまり心配していません。必要なのは、堅牢で保守が容易な、多くのスレッドから多くの同時接続を取得できる DAL だけです。

これについて何か助けてくれてありがとう。

4

1 に答える 1

4

SqlDataReaderCommandBehavior.CloseConnectionコマンドの実行時に指定すると、接続が閉じられます。とはいえ、どう見てもダサい感じです。

代わりに、メソッドにaSqlConnection を渡し、それを使用します。次に、呼び出し元は、それがいつ破棄されるかを制御できます。または、Action<SqlDataReader>開いているリーダーで実行する を取得し、アクションの実行後にメソッドがリーダーと接続の両方を閉じるようにします。もちろん、そのアクションは、リーダーに対して必要なすべてのことを行う必要があります。

于 2009-07-12T20:37:43.973 に答える