在C#中调用多个" SQL DataReader"的正确方法是什么?

时间:2014-11-10 08:04:39

标签: c# sql database linq

我调用ExecuteReader();来获取数据,然后我需要使用另一个查询获取另一个数据。我的结构总是这样:

class SomeClass
{
    public static void Main(String[] args)
    {
        SqlConnection sqlConn = new SqlConnection();
        sqlConn.ConnectionString = "some connection string" 

        SqlCommand SQLCmd = new SqlCommand();
        SQLCmd.CommandText = "some query";
        SQLCmd.Connection = sqlConn;
        sqlConn.Open();

        sqlReader = SQLCmd.ExecuteReader();

        while (sqlReader.Read())
        {
            //some stuff here
        }

        sqlReader.Dispose();
        sqlReader.Close();
        sqlConn.Close();

        SQLCmd.CommandText = "another query";
        sqlConn.Open();
        sqlReader = SQLCmd.ExecuteReader();

        while (sqlReader.Read())
        {
            //some other stuff here
        }

        sqlReader.Dispose();
        sqlReader.Close();
        sqlConn.Close();
    }
}

它们共享相同的连接字符串。他们还能分享什么?他们可以共享sqlConn.Open();吗?什么是资源分配和避免错误的正确方法?

它是按原样运作的。提前谢谢。

7 个答案:

答案 0 :(得分:4)

这就是我写所有内容的方式:

class SomeClass
{
 public static void Main(String[] args)
 {
  using (SqlConnection sqlConn = new SqlConnection("some connection string"))
  {
   sqlConn.Open();

   using (SqlCommand comm = new SqlCommand("some query", conn))
   using (var sqlReader = comm.ExecuteReader())
   {
    while (sqlReader.Read())
    {
     //some stuff here
    }
   }

   using (SqlCommand comm = new SqlCommand("some query", conn))
   using (var sqlReader = comm.ExecuteReader())
   {
    while (sqlReader.Read())
    {
     //some other stuff here
    }
   }
  }
 }
}

using语句处理块完成时处理项目。至于共享内容,您可以在命令之间保持连接打开。

排除所有这一切的最重要的事情就是连接,但如果一个项目是using而不管它在后台实际做了什么,我倾向于尊重IDisposable语句(由于是实施细节,因此可能会发生变化。

不要忘记,单个命令和单个阅读器中还有多个活动结果集(as demonstrated in this answer),您可以将阅读器推进到下一个结果集。

<小时/> 对于我如何编写所有这些内容,我略微轻率一点的答案是:

 return connection.Query<T>(procedureName, param, commandType: CommandType.StoredProcedure);

使用Dapper; - )

答案 1 :(得分:4)

在我的评论中提到 - 如果可能,将两个查询合并为一个然后(如果它仍然产生多个结果集),使用NextResult继续前进。

窃取亚当的structure,但随着这种变化:

class SomeClass
{
 public static void Main(String[] args)
 {
  using (SqlConnection sqlConn = new SqlConnection("some connection string"))
  {
   sqlConn.Open();

   using (SqlCommand comm = new SqlCommand("some query; some other query;", conn))
   using (var sqlReader = comm.ExecuteReader())
   {
    while (sqlReader.Read())
    {
     //some stuff here
    }
    if(sqlReader.NextResult())
    {
      while (sqlReader.Read())
      {
       //some other stuff here
      }
     }
    }
  }
 }
}

答案 2 :(得分:1)

正确的方法是在SqlConnection - 语句中包含SqlCommandusing。这将强制在使用块时调用对象Dispose,即使抛出异常也是如此。 (当前代码不是这种情况。)

中的某些内容
using(var cnn = new SqlConnection("connectionstring")){
    cnn.Open();
    using(var cmd = new SqlCommand("SELECT 1")){
       var reader = cmd.ExecuteReader();
       while(reader.Read()) { /* doStuff */ }
    }
}

无论方法如何,Close / Dispose都不会实际关闭连接,因为连接设置非常昂贵。它只会将连接返回到连接池,并允许其他命令/读者使用它。

答案 3 :(得分:1)

要管理资源,您可以使用using,如下所示    ......

 SQLCmd.CommandText = "some query";
 SQLCmd.Connection = sqlConn;
 sqlConn.Open();

//using will dispose reader automatically.
 using(sqlReader = SQLCmd.ExecuteReader())
{
   while (sqlReader.Read())
    {
    //some stuff here
    }
}
 //sqlReader.Dispose();
 //sqlReader.Close();
 //sqlConn.Close();

 SQLCmd.CommandText = "another query";
//no need to open connection again.
// sqlConn.Open();
// sqlReader = SQLCmd.ExecuteReader();

 using(sqlReader = SQLCmd.ExecuteReader())
{
   while (sqlReader.Read())
    {
    //some stuff here
    }
}
 //sqlReader.Dispose();
 //sqlReader.Close();
 //sqlConn.Close();

您只能对已实现using接口的类使用IDispose。 在您的示例中,您还可以使用SqlConnectionSqlCommand来使用代码块。

答案 4 :(得分:0)

使用'使用',您无需手动关闭和处理。

using (SqlConnection connection = new SqlConnection(connectionString)) 
{    
     connection.Open();
     SqlCommand command = new SqlCommand("spTest", connection);
     command.CommandType = CommandType.StoredProcedure;
     command.Parameters.Add(new SqlParameter("@employeeid", employeeID));
     command.CommandTimeout = 5;

     command.ExecuteNonQuery();
}

答案 5 :(得分:0)

每次需要时打开一个新连接是最佳做法。 ADO.net使用连接池来进行连接。 http://msdn.microsoft.com/it-it/library/8xx3tyca(v=vs.110).aspx

答案 6 :(得分:0)

不要忘记你的try catch语句:)

class SomeClass
{
 public static void Main(String[] args)
 {
  using (SqlConnection sqlConn = new SqlConnection("some connection string"))
  {
   try{
   sqlConn.Open();

   using (SqlCommand comm = new SqlCommand("some query", conn))
   using (var sqlReader = comm.ExecuteReader())
   {
    while (sqlReader.Read())
    {
     //some stuff here
    }
   }

   using (SqlCommand comm = new SqlCommand("some query", conn))
   using (var sqlReader = comm.ExecuteReader())
   {
    while (sqlReader.Read())
    {
     //some other stuff here
    }
   }
   }
   catch()
{
// Do exception catching here or rollbacktransaction if your using begin transact
}
finally
{
sqlConn.Close();
}
  }
 }
}