为什么要对我的数据库进行异步调用?

时间:2014-03-10 17:46:43

标签: c# .net sql-server asynchronous

我编写了一个与MSSQL数据库交互的服务器。它目前用.NET 4.0编写,并使用NHibernate作为ORM从数据库中检索信息。在阅读有关.NET 4.5和async / await关键字的介绍时,我很快就了解到了NHibernate does not have support for async/await

我不明白为什么向数据库发出异步调用会有所帮助。不是所有请求都在数据库级别排队吗?不同步只会增加失败点而不改进任何东西吗?

6 个答案:

答案 0 :(得分:4)

通常,好处是您可以在运行可能昂贵的(异步)操作时阻止当前正在执行的线程。在WPF / Windows窗体应用程序的上下文中,这意味着您不会阻止UI线程(如果请求来自该线程)并且您的应用程序仍然响应。

在Web应用程序(例如IIS)的上下文中,这意味着您在等待结果时释放池中的线程。由于您没有锁定线程,因此可以重用它来接受另一个请求,并在接受的连接方面产生更好的性能(不一定是时间/请求)。

答案 1 :(得分:2)

  

请不要所有请求都在数据库级别排队?

没有。阅读Understanding how SQL Server executes a query。任何名副其实的数据库服务器都可以同时运行数百个请求。仅当请求是相关的(例如,您需要将查询1的输出作为参数传递给查询2)或在事务约束下操作时(在事务中任何时候只能激活一个语句),序列化才是必需的。 / p>

异步调用至少有两个主要优点:

  • 资源使用情况。如果不考虑其他任何事情,只需将编程模型更改为事件驱动的异步模型,将导致应用程序可以驱动的吞吐量大幅增加。当然,这适用于后端应用程序(例如,Web服务器),而不适用于客户端用户驱动的应用程序,该应用程序将无法发送超出一个用户启动的内容。阅读High Performance Windows programs链接的文章。这也很重要,即使有点过时了:Asynchronous Pages in ASP.NET 2.0

  • 重叠请求。同步模型doe snot允许向后端发出查询,直到当前完成。很多时候,应用程序有必要的信息(params)来发出两个或更多不相关的请求,但它只是可以。执行异步调用允许控制线程发出所有并行请求,并在完成后恢复。

.Net 4.5任务,NHibernate都不支持异步数据库编程。好老BeginExecuteXXX实际上要强大得多,虽然有点晦涩难懂。

答案 2 :(得分:1)

NHibernate可以支持真正的异步调用。我已经在我自己的分支上实现了它

https://github.com/ReverseBlade/nhibernate-core/tree/nh_4.5.1

您可以查看并编译。它是针对.net 4.5.1编译的。它与标准的nhibernate兼容并通过所有测试。 然后你可以使用像.ToListAsync();或GetAsync(),它将进行真正的异步调用。

如果您需要帮助,可以撰写评论。祝你好运

答案 3 :(得分:1)

好消息。自v 5.0以来,NHibernate支持async / await开箱即用

答案 4 :(得分:0)

您可能会将语言功能与设计模式混淆; async是帮助您管理后台任务的语法糖,而异步任务只是意味着您正在运行两个或更多线程。

仅仅因为NHibernate不支持async并不意味着你不能异步运行。这对用户非常有利,因为您不想在对数据库/服务执行(相对)长时间运行的查询时冻结UI,尤其是在服务器陷入困境时。

我想你可以把这看作是一个失败点,但实际上只是一些方面:

  1. 例外 - 无论如何,您在一个线程上遇到此问题,但您应该优雅地处理您遇到的任何数据库错误。
  2. UI管理 - 您不希望让用户以触发多个查询的方式与UI进行交互,因此您可以禁用按钮等。
  3. 结果处理 - 查询完成后,您需要确保将数据封送回UI线程。在C#中,这可以通过Invoke / BeginInvoke完成,不管您是在WinForms还是WPF中确定详细信息。
  4. 编辑:

    一些假设WPF和至少.NET 4.0的示例框架代码

    Task.Factory.StartNew(() =>
    {
        using (var client = new dbClient())
        {
            // Perform query here
    
            this.Dispatcher.BeginInvoke(new Action(() =>
            {
                // Set data source, etc, i.e.
                this.Items = result;
            }));
        }
    }).ContinueWith(ex => Logger.LogException(ex), TaskContinuationOptions.OnlyOnFaulted);
    

答案 5 :(得分:0)

你说:

  

请不要所有请求都在数据库级别排队?

如果通过“队列”你的意思是“单一服务队列”而不是答案是否定的。 SQL Server是一种高度异步和多线程的服务,可以同时为许多查询提供服务。

即使在物理层面,排队(即物理设备服务)也会同时分配在多个CPU核心上,以及组成磁盘阵列的物理磁盘数量。

因此,对SQL Server进行异步调用的原因是能够将一些多线程/多服务容量用于您自己的服务。