如何异步运行NHibenate查询?

and*_*nov 20 .net nhibernate asynchronous linq-to-nhibernate

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

这是一篇关于Linq to SQL中的异步查询的文章.

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

谢谢,安德烈

Mau*_*fer 12

请注意,异步数据库调用本身并不意味着更好的整体可伸缩性.我建议阅读文章" 我的数据库应该调用异步吗? "进行深入分析.以下是该文章的引用:

一位受人尊敬的DB/Web架构师甚至说:
对于使用异步操作来减少Web服务器上被阻塞线程数的数据库应用程序几乎总是浪费时间.小型Web服务器可以轻松处理比数据库后端可以同时处理的更多同时阻塞请求的方式.相反,请确保您的服务调用在数据库中很便宜,并将并发执行的请求数限制为您已测试的数字以正常工作并最大化整体事务吞吐量.

  • @BorisBucha .NET 4.5与此无关.仅仅因为您可以更轻松地在C#代码中表达异步代码并不意味着Web服务器和数据库自动更具可伸缩性. (9认同)
  • 截至2012年8月,该论点无效(在.net 4.5 rtm之后).既然异步代码的成本显着降低,那么以异步方式编写db操作绝对是可以的.但是在这个时刻,NHibernate仍然没有支持.希望这很快就会变得无用:) (8认同)
  • 我相信它确实如此.确保你不能通过异步方式调用数据库来提高数据库速度,但是你的网络服务器更容易垂直扩展.线程越少意味着内存越少.如果我可能会大大过分简化主题,我可以说通过利用异步你总是*赢.在最坏的情况下,性能保持不变.在最好的情况下,只需禁止io-bound任务占用Threadpool,就可以显着改善它.开发成本几乎没有,所以我没有看到任何理由不以异步方式从.net4.5开始做所有事情. (6认同)
  • @tugberk的不同之处在于延迟不会使数据库使用任何CPU或I/O. 这不是真正的负担.因此,实验没有显示我链接的文章中描述的负载转移效应. (3认同)
  • @MauricioScheffer你可能想再次检查你的答案:http://www.tugberkugurlu.com/archive/asynchronous-database-calls-with-task-based-asynchronous-programming-model-tap-in-asp-net-mvc- 4 (2认同)

Fir*_*iro 12

可以使用Futures重写多个异步调用

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
Run Code Online (Sandbox Code Playgroud)

可以替换为

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
Run Code Online (Sandbox Code Playgroud)

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


Die*_*hon 9

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

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


Kor*_*yem 8

从 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();
Run Code Online (Sandbox Code Playgroud)

更新实体

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();
}
Run Code Online (Sandbox Code Playgroud)

来源文章