我应该升级为能够为SqlDataReader使用新的异步方法吗?

时间:2014-02-27 13:12:42

标签: c# .net asynchronous .net-4.0 .net-4.5

我正在开发一个在.NET 4.0上运行的大型项目。该框架使用ADO.NET进行数据库调用,我们目前正在添加异步API方法。 SqlCommand类包含APM方法SqlCommand.BeginExecuteReader()SqlCommand.EndExecuteReader(),但SqlDataReader没有异步实现。
SqlCommand.ExecuteReader()完成后,我想使用SqlDataReader迭代结果。 Microsoft在.NET 4.5中引入了SqlDataReader的异步方法,所以我不能在4.0中使用它们。

问题:我们应该升级为能够使用SqlDataReader的异步(TAP)方法吗? 如果我们这样做,为什么?

  

我搜索了网络和stackoverflow很多答案,但我似乎只是找到了这个实现。它没有告诉我这些新实现会带来什么好处。

.NET 4.0实现

这里我们使用SqlCommand的异步方法,但我们不能使用SqlDataReader的新异步方法,例如SqlDataReader.ReadAsync()

private Task<IDataReader> ExecuteReaderAsync(IDbCommand dbCommand)
{
    var sqlCommand = CheckIfSqlCommand(dbCommand);
    PrepareExecuteReader(dbCommand);

    return Task<IDataReader>
        .Factory
        .FromAsync(sqlCommand.BeginExecuteReader, sqlCommand.EndExecuteReader, null);
}

private void ReadAll(Task<IDataReader> readerTask)
{
    var reader = readerTask.Result;

    while (reader.Read()) // Should this be asynchronously?
    {
        // Do something
    }
}

public Task<IDataReader> Foo(IDbCommand dbCommand) {
    return ExecuteReaderAsync(dbCommand)
        .ContinueWith(readerTask => ReadAll(readerTask));
}

.NET 4.5实现

在.NET 4.5中,我们可以使用async / await关键字,我们可以使用SqlDataReader的新异步方法,如SqlDataReader.ReadAsync()

private async Task<SqlDataReader> ExecuteReaderAsync(SqlCommand dbCommand)
{
    PrepareExecuteReader(dbCommand);

    return await dbCommand.ExecuteReaderAsync();
}

private async Task ReadAll(SqlDataReader reader)
{
    while (await reader.ReadAsync()) // Should this be asynchronously?
    {
        // Do something
    }
}

public async Task<IDataReader> Foo(SqlCommand dbCommand)
{
    var reader = await ExecuteReaderAsync(dbCommand);
    await ReadAll(reader);

    return reader;
}

1 个答案:

答案 0 :(得分:3)

理论上的好处是您的应用程序将使用更少的线程,因此在线程开销上消耗更少的内存和CPU资源。反过来,这为您的应用程序或其他系统活动留下了更多可用资源,从而提高了应用程序的性能和可伸缩性。

对于接收大量同时请求的应用程序,收益可能很大。但是,您只能通过测试特定应用程序找到您将看到的实际差异。 This是一篇很好的文章,深入细节。

我的观点是,如果您没有发现异步DataReader代码更难理解,读取和调试,那么继续使用它。它将与您处理命令代码的方式一致,并且异步通常被认为是现代最佳实践。你有什么损失?

但是,我想提一下,你应该考虑使用更高级别的API,即ORM。我认为Entity Framework和nHibernate目前是最受.NET欢迎的。 EF6具有内置的异步支持,并且对于异步的典型查询,您可以简单地使用类似ToListAsync()的内容。请参阅this作为开始。