How to manage SqlDataReaders in a data access layer?

♀尐吖头ヾ 提交于 2019-12-04 19:32:55

Your method ExecuteReader will close the connection before returning the Reader. Instead it should be implemented something like:

public IDataReader ExecuteReader(string cmdTxt)    
{        
    SqlConnection conn = new SqlConnection(...);
    try
    {
        SqlCommand cmd = new SqlCommand(cmdTxt, conn);
        conn.Open();                
        return cmd.ExecuteReader(CommandBehavior.CloseConnection);           
    }
    catch
    {
        conn.Close();
        throw;
    }
}

Callers of the ExecuteReader method will need to dispose the IDataReader:

using(IDataReader reader = ExecuteReader(commandText))
{
    ...
} // reader will be disposed here and will close the connection.

Note that the above does not call Dispose on the SqlCommand object. In my experience and from looking at SqlCommand with Reflector it's not necessary as long as the SqlConnection is disposed. But I believe the following will work if you do want to dispose it:

public IDataReader ExecuteReader(string cmdTxt)    
{        
    SqlConnection conn = new SqlConnection(...);
    SqlCommand cmd = null;
    try
    {
        cmd = new SqlCommand(cmdTxt, conn);
        conn.Open();                
        IDataReader reader = 
            cmd.ExecuteReader(CommandBehavior.CloseConnection);           
        cmd.Dispose();
        return reader;
    }
    catch
    {
        if (cmd != null) cmd.Dispose();
        conn.Close();
        throw;
    }
}

It's very important that you close and/or dispose your data reader after using it then everyone who wants to use your DataFactory should remember to do that.I think it's a good idea to return a DataTable instead of SqlDataReader so that your DataFactory is not dependent to SqlDataReader.

I mean :

public DataTable ExecuteReader(string cmdTxt)
    {
        using(SqlConnection conn = new SqlConnection(ConnectionString))
        {
           using(SqlCommand cmd = new SqlCommand(cmdTxt, conn))
           {
                conn.Open();
                using(SqlDataReader reader=cmd.ExecuteReader())
                {
                    DataTable dt=new DataTable();
                    dt.Load(reader);
                    return dt;
                }

           }
        }
    }

EDIT: Good point.I don't like data tables either ( We use NHibernate so I actually don't use data tables in our applications) So if you'd like to map a data reader to your own objects maybe you can have a data mapper that maps data reader to your own objects I mean:

public T[] ExecuteReader<T>(string cmdTxt)
    {
        using(SqlConnection conn = new SqlConnection(ConnectionString))
        {
           using(SqlCommand cmd = new SqlCommand(cmdTxt, conn))
           {
                conn.Open();
                using(SqlDataReader reader=cmd.ExecuteReader())
                {
                    var result=new List<T>();
                    while(reader.Read())
                         result.Add(ObjectMapper.MapReader<T>(reader));

                    return result.ToArray();
                }

       }
    }
}

What I do is I create an XML file with my queries and use an XSLT transformation to generate my DAL code CS files. You can go as fancy as you like, declare parameters in the XML and generate methods with appropriate signatures in the XSLT etc etc. I have a blog entry that covers, for a related topic, how to integrate the XSLT transformation into your Visual Studio project. Now one may argue that using a typed dataset is the same thing and is a free lunch, but in my case I use asynchronous DAL based on BeginExecute/EndExecute. None of the VS tools gets this approach right so I basically had to build my own.

I would say it's not really decoupling enough - basically any module you have with "using System.Data.SqlClient" is coupled to your database. The whole point of a DAL is that the application is coupled to the DAL and the DAL is coupled to the database.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!