全部任务,连接正在关闭

时间:2016-09-23 13:11:13

标签: c# async-await sqldatareader

我尝试使用Task.WhenAll执行多个SqlDataReaders。但是当等待任务时,我得到了

  

" System.InvalidOperationException:无效的操作。连接   已关闭"。

创建任务:

    public Task<SqlDataReader> GetSqlDataReader1(int recordCount)
    {
        using (var sqlCon = new SqlConnection(ConnectionString))
        {
            sqlCon.Open();
            using (var command = new SqlCommand("sp_GetData", sqlCon))
            {
                command.Parameters.Clear();
                command.Parameters.Add(new SqlParameter("@recordCount", recordCount));
                command.CommandType = System.Data.CommandType.StoredProcedure;
                return command.ExecuteReaderAsync();
            }
        }
    }

我的&#34; SqlDataReader&#34;方法:

/root/mydir

在执行Task.WhenAll时我不应该打开数据库连接,还是我错过了什么?

3 个答案:

答案 0 :(得分:6)

可以将CommandBehavior.CloseConnection传递给ExecuteReaderAsync。然后,连接将保持打开状态,直到返回的datareader对象关闭为止:请参阅MSDN herehere。在这种情况下,SqlConnection不需要在using语句中。

像这样:

public Task<SqlDataReader> GetSqlDataReader1(int recordCount)
{
    var sqlCon = new SqlConnection(ConnectionString);
    sqlCon.Open();

    using (var command = new SqlCommand("sp_GetData", sqlCon))
    {
        command.Parameters.Clear();
        command.Parameters.Add(new SqlParameter("@recordCount", recordCount));
        command.CommandType = System.Data.CommandType.StoredProcedure;
        return command.ExecuteReaderAsync(CommandBehavior.CloseConnection);
    }
}

答案 1 :(得分:2)

更新:我要离开这里了,但我记得你不能将yield和{{1}结合起来至少,还没有。

请注意,即使使用await关键字,调用command.ExecuteReaderAsync()也不会停止执行该方法。这是return方法的重点。因此,在该函数调用之后,代码将立即退出_Async()块。这样就可以在您有机会使用连接对象从DataReader中读取之前将其处理掉。

请尝试返回using

Task<IEnumerable<IDataRecord>>

请注意,有一个&#34;陷阱&#34;有这种模式。每个public async Task<IEnumerable<IDataRecord>> GetSqlDataReader1(int recordCount) { using (var sqlCon = new SqlConnection(ConnectionString)) using (var command = new SqlCommand("sp_GetData", sqlCon)) { command.Parameters.Add("@recordCount", SqlDbType.Int).Value = recordCount; command.CommandType = System.Data.CommandType.StoredProcedure; sqlCon.Open(); var rdr = await command.ExecuteReaderAsync(); while (rdr.Read()) { yield return rdr; } } } 使用相同的对象,因此如果您不小心,可能会发生一些奇怪的事情。我建议进一步更改此包含代码,将来自yield return对象中每个记录的数据放入其自己的(强类型)对象实例中:

rdr

答案 2 :(得分:2)

  我错过了什么吗?

您是否试图获得没有基础连接的SqlDataReader?我认为这不会很好。你从读者那里读到了什么?连接已经关闭。

因此,您可能只需在关闭连接之前阅读实际数据:

public async Task<List<T>> GetData1(int recordCount)
{
    using (var sqlCon = new SqlConnection(ConnectionString))
    {
        sqlCon.Open();
        using (var command = new SqlCommand("sp_GetData", sqlCon))
        {
            command.Parameters.Clear();
            command.Parameters.Add(new SqlParameter("@recordCount", recordCount));
            command.CommandType = System.Data.CommandType.StoredProcedure;

            var result = new List<T>();
            var reader = await command.ExecuteReaderAsync();
            // TODO: use `reader` to populate `result`
            return result;
        }
    }
}