使用Using语句的SQLConnection,如何在其中调用SQLDataReader?

3

我想确认一下这是否是调用连接和从数据库获取数据的最佳方法,或者我应该如何在using语句之外调用datareader(为了更快地关闭连接)?还是你有什么个人建议要更改这个代码?

using (SqlConnection cn = new SqlConnection(connStr))
        {
            using (SqlCommand cm = new SqlCommand(connStr, cn))
            {  
                cm.CommandType = CommandType.StoredProcedure;
                cm.CommandText = "GetExchRatesByDate";
                cm.Parameters.Add("@Date", SqlDbType.VarChar).Value = txtStartDate.Text;
                cn.Open();
                SqlDataReader dr = cm.ExecuteReader();

                while (dr.Read())
                {
                    firstName = (string)dr["GivenName"];
                    lastName = (string)dr["sn"];;
                }
                dr.Close();
            }
        }
5个回答

5

如果要读取数据,就必须在using语句中打开连接,否则无法成功调用数据读取器。

按照您的方式,连接将关闭得足够快,并且并不会真正“关闭”。它将被返回到连接池(假设您正在使用连接池)。由于您可能正在使用连接池,因此在这种情况下,您不需要担心连接关闭的速度,因为应用程序的其他部分需要连接时将从池中获取可用的连接。这是假定您没有一个非常高流量的应用程序,在那种情况下,它可能变得重要,但那是许多、许多、许多并发用户,您可以通过增加池中的连接数量来缓解这个问题。

Chris也提出了一个很好的观点:应该放在using语句中:

  SqlDataReader dr = cm.ExecuteReader();

                while (dr.Read())
                {
                    firstName = (string)dr["GivenName"];
                    lastName = (string)dr["sn"];;
                }
                dr.Close();

在这种情况下,如果您的读取器出现异常,它将永远不会到达 dr.Close();,因此它会比实际需要保持打开更长的时间(甚至可能是应用程序的生命周期)。

数据读取器


谢谢,我只是想确认这是一种可接受的获取数据的方式。我将继续使用这段代码。 - Spooks

5

using语句外部您不能调用SqlDataReader,因为所有声明的变量都将被释放,并且您需要打开连接以读取数据。最好编写一个将返回对象或甚至您对象列表的对象。

public class MyObject {
    public string FirstName { get; set; }
    public string Surname { get; set; }
}

public IEnumerable<MyObject> GetObjects() {
    ICollection<MyObject> myObjects = new List<MyObject>();

    using (SqlConnection cn = new SqlConnection(connStr))
    {
        using (SqlCommand cm = new SqlCommand(connStr, cn))
        {  
            cm.CommandType = CommandType.StoredProcedure;
            cm.CommandText = "GetExchRatesByDate";
            cm.Parameters.Add("@Date", SqlDbType.VarChar).Value = txtStartDate.Text;
            cn.Open();

            using(SqlDataReader dr = cm.ExecuteReader()) 
                while (dr.Read()) {
                    MyObject myObject = new MyObject();
                    myObject.FirstName = (string)dr["GivenName"];
                    myObject.Surname = (string)dr["sn"];
                    myObjects.Add(myObject);
                }
        }
    }
    return myObjects;
}

2
数据读取器实现了IDisposable接口,因此也应该包装在using语句中。其他方面看起来都很好。

1

其他人已经讲过了,但我喜欢使用的另一种方法是AddWithValue:

cm.Parameters.Add("@Date", SqlDbType.VarChar).Value = txtStartDate.Text;

可以写成:

cm.Parameters.AddWithValue("@Date", txtStartDate.Text);

0

我会考虑将SQLConnection放入工厂方法中(如果它被称为loads)。

此外,我不会在dr.Read周围使用while循环。您只期望一个答案,那么当没有结果或有许多结果时会发生什么??? 不太确定我是否喜欢强制转换,但可能还好。

我假设您已经在此代码周围进行了单元测试,并传递了连接字符串等...(显然,工厂想法会使单元测试更加困难,因此可能不值得做...)

您的using语句看起来对我来说很好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接