SqlConnection 和 SqlDataReader 的复用

Posted

技术标签:

【中文标题】SqlConnection 和 SqlDataReader 的复用【英文标题】:Reuse of SqlConnection and SqlDataReader 【发布时间】:2012-04-26 04:20:01 【问题描述】:

如果我想在不同的表上运行多个 SELECT 查询,我可以对所有表使用相同的 SqlDataReader 和 SqlConnection 吗?以下是明智的吗? (我输入得很快,所以它缺少 try/catch):

mysqlCommand myCommand = new MySqlCommand("SELECT * FROM table1", myConnection);

myConnection.Open();
SqlDataReader myDataReader = myCommand.ExecuteReader();

while(myReader.Read())

    //Perform work.


myCommand.commandText = "SELECT * FROM table2";

myReader = myCommand.ExecuteReader();

while(myReader.Read())

    //Perform more work


myReader.Close();
myConnection.Close();

非常感谢。

【问题讨论】:

你应该考虑使用实体框架。 也许有帮助:***.com/questions/9705637/… 你上面的代码有错误吗?如果没有,那肯定没问题。 你不要重复使用阅读器,ExecuteReader 会创建一个新阅读器。 【参考方案1】:

您可以对它们中的每一个使用相同的连接,只要您不尝试在不同线程的同一连接上同时执行多个查询。

至于数据阅读器,您实际上并没有重用阅读器,每次调用ExecuteReader都会返回一个新阅读器的新实例,您所重用的只是保持对阅读器的引用的变量.这里存在一个问题,您只是显式地关闭了最后一个阅读器,而让第一个阅读器在以后的某个时间被 GC。

您也可以重复使用命令,但请记住,如果您提供参数等。您需要为下一个查询清除它们,除非它们也适用于下一个查询。

您应该使用try/finally 块来确保清理资源,或者在这里快速更改您的代码以使用using 语句来确保资源清理,即使存在阻止其余部分的异常执行的代码。

using (var myConnection = GetTheConnection())

  myConnection.Open();

  var myCommand = new MySqlCommand("SELECT * FROM table1", myConnection))
  using (var myDataReader = myCommand.ExecuteReader())
  
    while(myReader.Read())
    
      //Perform work.
    
   // Reader will be Disposed/Closed here

  myCommand.commandText = "SELECT * FROM table2";
  using (var myReader = myCommand.ExecuteReader())
  
    while(myReader.Read())
    
      //Perform more work
    
   // Reader will be Disposed/Closed here
 // Connection will be Disposed/Closed here

注意:GetTheConnection 只是用于获取连接实例的机制的占位符函数。

【讨论】:

谢谢。所以我想我只需要在每次执行后关闭阅读器对象。 实际上我正在为 SqlCommand 提供参数,我想我应该使用 myCommand.Parameters.Clear()。非常感谢。 @PaulG,根据经验,每当一个类实现 IDisposable 时,您都应该尽早处理它。就读者而言,它们会占用数据库服务器资源,直到它们被关闭或处置,因此您希望在完成它们后立即处置它们。现在我看到你在使用 MySQL,所以我不知道那里的资源使用情况,但是对于基于服务器的 DBMS 系统,如 Oracle 或 SQL Server,情况就是这样,你应该始终假设是这种情况。【参考方案2】:

我通常使用适配器,所以我对读者的细节生疏,但我认为你在正确的轨道上。

您的代码中需要注意的一点是,每次调用 ExecuteReader 都应该生成一个新的数据读取器。您可能正在重用变量名称,但对现有阅读器的引用将被丢弃,并在每次调用时被新的阅读器替换。重点是,在使用 ExecuteReader 获取新的阅读器之前关闭之前的阅读器。

【讨论】:

以上是关于SqlConnection 和 SqlDataReader 的复用的主要内容,如果未能解决你的问题,请参考以下文章

SqlCommand.CommandTimeout 和 SqlConnection.ConnectionTimeout 有啥区别?

c#是不是关闭sqlconnection和sqldatareader?

如何判断SqlConnection是否附加了SqlDataReader?

using (SqlConnection connection = new SqlConnection(connectionString))

.Net SqlConnection、服务器身份验证和证书固定

处理SqlConnection、SqlDataReader、SqlCommand 时要捕获哪些异常?