【问题标题】:Can I keep a SqlDataReader "alive" after closing connection?关闭连接后我可以保持 SqlDataReader “活动”吗?
【发布时间】:2014-11-07 09:17:38
【问题描述】:

连接关闭后有什么方法可以访问SqlDataReader

或者是否有任何与SqlDataReader 等效的对象,我可以将阅读器存储到它们中并稍后在对象上进行处理?

我正在从服务器接收一个数据集,所以我不能使用普通类来处理这种数据,我的模型如下所示:

public class OneToNinetyNine
{
    public List<Cities> listCities;
    public string CityID;
    public DateTime DateFrom;
    public DateTime DateTo;
    // this is the reader that I attempt to pass to the views 
    public SqlDataReader SqlReader; 
}

【问题讨论】:

  • 不,只使用你自己的类来存储字段。
  • 您需要使用Load方法将数据读入DataSetDataTable,然后您可以关闭连接。
  • @Ben:如果他已经使用了SqlDataReader,他甚至不需要DataTable/DataSet。他只需要从阅读器的字段中适当地初始化类。
  • @TimSchmelter,他关闭连接后会起作用吗?
  • @hoangnnm:如果您可以加载DataTable,您也可以加载输入的List&lt;OneToNinetyNine&gt;(或其他)。

标签: c# asp.net-mvc dynamic sqldatareader


【解决方案1】:

连接关闭后不能使用DataReader,因为它需要使用连接从数据源中检索数据。

您需要使用Load方法将数据读入DataSetDataTable,然后您可以关闭连接。

【讨论】:

  • 谢谢,我会坚持使用数据集
【解决方案2】:

您可以将SqlDataAdapter 中的数据存储到DataSet 以供将来使用:

DataSet ds = new DataSet();
SqlCommand mycommand = new SqlCommand("sql statement");
using (SqlDataAdapter adapter = new SqlDataAdapter(mycommand))
{
    adapter.Fill(ds);
}

【讨论】:

    【解决方案3】:

    有什么方法可以在连接关闭后访问 SqlDataReader?

    没有。连接关闭后,阅读器将无法从连接中读取数据。

    但是,可以通过使用指定CommandBehavior.CloseConnectionExecuteReaderExecuteReaderAsync 调用来反转DataReaderConnection 之间的关系寿命。在这种模式下,当 Reader 关闭(或 Disposed)时,连接也会关闭。

    当您不一定要一次性检索和具体化查询中的所有数据时,使用 CommandBehavior.CloseConnection 的长寿命数据读取器会很有用,例如数据分页或临时类型惰性求值。这是选项 2,如下所示。

    选项 1:打开连接,检索并实现所有数据,然后关闭所有内容

    与其他答案一样,在许多情况下,对于小而明确的数据提取,最好像这样打开连接、创建命令、执行读取器并一次性提取和实现所有数据:

    public async Task<Foo> GetOneFoo(int idToFetch)
    {
       using (var myConn = new SqlConnection(_connectionString))
       using (var cmd = new SqlCommand("SELECT Id, Col2, ... FROM Foo WHERE Id = @Id"))
       {
          await myConn.OpenAsync();
          cmd.Parameters.AddWithValue("@Id", idToFetch);
          using (var reader = await cmd.ExecuteReaderAsync())
          {
             var myFoo = new Foo
             {
                Id = Convert.ToInt32(reader["Id"]),
                ... etc
             }
             return myFoo; // We're done with our Sql data access here
          } // Reader Disposed here
       } // Command and Connection Disposed here
    }
    

    选项 2:打开连接、执行命令并使用长寿阅读器

    使用CommandBehavior.CloseConnection,我们可以创建一个长寿命的阅读器并延迟关闭连接,直到不再需要Reader

    为了防止像 DataReaders 这样的数据访问对象渗入更高层代码,yield return 生成器可用于管理读取器的生命周期 - 同时确保读取器(以及连接)在不再需要生成器。

    public async Task<IEnumerable<Foo>> LazyQueryAllFoos()
    {
       // NB : No `using` ... the reader controls the lifetime of the connection.
       var sqlConn = new SqlConnection(_connectionString);
       // Yes, it is OK to dispose of the Command https://stackoverflow.com/a/744307/314291
       using (var cmd = new SqlCommand(
            $"SELECT Col1, Col2, ... FROM LargeFoos", mySqlConn))
       {
          await mySqlConn.OpenAsync();
          var reader = await cmd.ExecuteReaderAsync(CommandBehavior.CloseConnection);
          // Return the IEnumerable, without actually materializing Foos yet.
          // Reader and Connection remain open until caller is done with the enumerable
          return GenerateFoos(reader);
       }
    }
    
    // Helper method to manage lifespan of foos
    private static IEnumerable<Foo> GenerateFoos(IDataReader reader)
    {
        using(reader)
        {
           while (reader.Read())
           {
              yield return new Foo
              {
                  Id = Convert.ToInt32(reader["Id"]),
                  ...
              };
           }
        } // Reader is Closed + Disposed here => Connection also Closed.
    }
    

    备注

    • 在 C#6 中,async 代码目前还不能使用 yield return,因此需要将辅助方法从异步查询中分离出来(不过,我相信辅助方法可以移动到本地函数中)。
    • 调用GenerateFoos 的代码确实需要注意不要将 Enumerable(或其迭代器)保持在所需的时间之外,因为这将使底层的 Reader 和 Connection 保持打开状态。

    【讨论】:

    • Nb 不要在 Conn 或阅读器周围使用。不需要 $ 字符串
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-23
    • 1970-01-01
    相关资源
    最近更新 更多