如何异步运行NHibenate查询?

时间:2010-03-21 04:41:46

标签: .net nhibernate asynchronous linq-to-nhibernate

提高服务器应用程序可伸缩性的一种方法是异步运行IO绑定操作(读取文件,套接字,Web请求,数据库请求等)。这并不意味着在ThreadPool中运行它们,它只会在执行操作时阻塞线程。正确的方法是使用异步API(BeginRead,BeginGetResponse,BeginExecuteReader等)。这个问题在CLR vi C#书中有详细描述。

以下是关于asynchronous queries in Linq to SQL的一些文章。

有任何方法可以异步执行Nhibernate查询吗?怎么样Linq到NHibernate?

谢谢你, 安德烈

5 个答案:

答案 0 :(得分:12)

请注意,异步数据库调用本身并不意味着更好的整体可伸缩性。我建议您阅读文章“Should my database calls be Asynchronous?”进行深入分析。以下是该文章的引用:

  

一位受人尊敬的DB / Web架构师就这样做了   至于说:
  对于数据库   使用异步操作的应用程序   减少阻塞线程的数量   在Web服务器上几乎总是一个   完全浪费时间。一个小网站   服务器可以轻松处理更多方式   同时阻止请求比   您的数据库后端可以处理   同时。而是确保你的   服务电话很便宜   数据库,并限制数量   同时执行对a的请求   你测试过的号码   正确并最大化整体   交易吞吐量。

答案 1 :(得分:12)

可以使用期货重写多个异步调用

var footask = QueryFooAsync();
var bartask = QueryBarAsync();
var baztask = QueryBazAsync();

var foos = await footask;
var bars = await bartask;
var baz = await baztask;

// do something with foos, bars, baz

可以替换为

var foos = session.Query<Foo>().....ToFuture();
var bars = session.Query<Bar>().....ToFuture();
var baz = session.Query<Bazes>().....ToFutureValue();

await Task.Factory.StartNew(() => var ignored = baz.Value)  // await the results

// do something with foos, bars, baz

这甚至比异步代码更有利于往返时间只支付一次而不是3次。

答案 2 :(得分:9)

不幸的是,没有。 NHibernate不会像L2S那样公开命令执行的内部实现。

您必须使用线程池或为NH创建补丁以添加异步查询支持。这对社区非常欢迎,并且可以进行一次很好的锻炼(但这根本不是微不足道的)

答案 3 :(得分:1)

尽管NH中仍然不支持异步查询,但您仍然可以部分克服从请求线程运行(长时间运行)db调用的一些不良影响。

您想要的是在短暂运行和长时间运行之间拆分Threadpool。当然,这对于Threadpool和TPL的实际实现是不可能的,但是你可以通过编写自己的生产者/消费者队列以及等待的项目和自定义的可靠性来帮助自己。

请查看我放在一起的示例:https://gist.github.com/3746240

代码是由Joseph Albahari和Ben Albahari撰写的精彩书籍“C#5.0 in a Nutshell:The Definitive Reference”中的复制/粘贴,由我完成修改,导致调度程序为项目处理创建专用的工作线程。

答案 4 :(得分:1)

从NHibernate v5开始,现在完全支持异步!

这里有一些漂亮的例子:

Customer customer = await session.GetAsync<Customer>(1);

List<Customer> customers = await session.Query<Customer>().ToListAsync();

Customer customer = await session.Query<Customer>()
.Where(x => x.Name.Contains("Customer 1"))
.SingleOrDefaultAsync();

更新实体

using (ISession session = sessionFactory.OpenSession())
using (ITransaction transaction = session.BeginTransaction())
{
    Customer customer = await session.GetAsync<Customer>(1);
    customer.Name = "Customer 3";
    await session.SaveOrUpdateAsync(customer);
    await transaction.CommitAsync();
}

Source article