在调用ExecuteReader时从基本DAL类处理SqlConnection

时间:2009-07-12 20:32:59

标签: c# .net data-access-layer sqlconnection idatareader

我已经分配了一个项目,其中DAL由一个基类组成,该基类具有返回IDataReader,Object(int,string等)或DataSet的函数。 ExecuteNonQuery函数也存在。此DAL仅访问USP(SQL Server),并使用MS的SqlHelper来执行查询。以下是基础的两个示例函数:

    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);
    }
    ...
}

然后有BLL类调用DAL函数,并使用基于从IDataReader对象读取的数据填充对象(例如Order对象):

    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,我们只需要一个可靠且易于维护的服务器,可以从多个线程中获取许多并发连接。

提前感谢您提供任何帮助。

1 个答案:

答案 0 :(得分:4)

如果在执行命令时指定SqlDataReader

CommandBehavior.CloseConnection将关闭连接。然而,无论如何它感觉有点难看。

相反,将SqlConnection 传递给方法并使用它。然后呼叫者可以控制何时处理掉。或者,使用打开的阅读器执行Action<SqlDataReader>,并在执行操作后使方法关闭阅读器和连接。当然,该行动必须与读者一起做所需的一切。