如何异步运行NHibenate查询?

时间:2021-06-20 21:15:46

One way to increase scalability of the server application is to run IO-bound operation (reading files, sockets, web requests, database requests etc) asynchronously. This does not mean run them in the ThreadPool which will just block threads while operation is being executed. The correct way is to use asynchronous API (BeginRead, BeginGetResponse, BeginExecuteReader etc). The problem is well described in CLR vi C# book.

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

Here is some article about asynchronous queries in Linq to SQL.

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

Are any ways to execute Nhibernate query asynchonously? What about Linq to NHibernate?

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

Thank you, Andrey

谢谢,安德烈

5 个解决方案

#1


9  

Unfortunately, no. NHibernate does not expose the internal implementation of the command execution in the way L2S does.

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

You'll have to use the threadpool OR create a patch for NH to add asynchronous query support. That would be very welcome by the community and would make for a nice exercise (but it's not trivial at all)

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

#2


12  

Note that async database calls do NOT imply better overall scalability by themselves. I recommend reading the article "Should my database calls be Asynchronous?" for an in-depth analysis. Here's a quote from that article:

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

One respected DB/Web architect went so far as to say:
For database applications using async operations to reduce the number of blocked threads on the web server is almost always a complete waste of time. A small web server can easily handle way more simultaneous blocking requests than your database back-end can process concurrently. Instead make sure your service calls are cheap at the database, and limit the number of concurrently executing requests to a number that you have tested to work correctly and maximize overall transaction throughput.

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

#3


12  

multiple async calls can be rewritten with Futures

可以使用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

can be replaced with

可以替换为

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

this even has the benefit over async code that the roundtrip time is only paid once instead of 3 times.

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

#4


1  

Although there is still no support for async queries in NH, you can still partially overcome some of the undesired effects of running (long-running) db calls from request thread.

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

What you want is to split Threadpool between short-running and long-running operations. Of course this is not possible with actual implementation of Threadpool and TPL but you can help yourself quite eassilly by writing your own Producer/Consumer queue with awaitable items and customized concurency.

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

Please have a look at example i have put together : https://gist.github.com/3746240

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

Code is copy/pasted from great book "C# 5.0 in a Nutshell: The Definitive Reference" by Joseph Albahari and Ben Albahari with modification done by me causing the scheduler to create dedicated worker threads for items proccesing.

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

#5


0  

As of NHibernate v5, async is now fully supported!

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

Here are some nifty examples:

以下是一些漂亮的例子:

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();

Updating an entity

更新实体

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

来源文章

#1


9  

Unfortunately, no. NHibernate does not expose the internal implementation of the command execution in the way L2S does.

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

You'll have to use the threadpool OR create a patch for NH to add asynchronous query support. That would be very welcome by the community and would make for a nice exercise (but it's not trivial at all)

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

#2


12  

Note that async database calls do NOT imply better overall scalability by themselves. I recommend reading the article "Should my database calls be Asynchronous?" for an in-depth analysis. Here's a quote from that article:

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

One respected DB/Web architect went so far as to say:
For database applications using async operations to reduce the number of blocked threads on the web server is almost always a complete waste of time. A small web server can easily handle way more simultaneous blocking requests than your database back-end can process concurrently. Instead make sure your service calls are cheap at the database, and limit the number of concurrently executing requests to a number that you have tested to work correctly and maximize overall transaction throughput.

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

#3


12  

multiple async calls can be rewritten with Futures

可以使用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

can be replaced with

可以替换为

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

this even has the benefit over async code that the roundtrip time is only paid once instead of 3 times.

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

#4


1  

Although there is still no support for async queries in NH, you can still partially overcome some of the undesired effects of running (long-running) db calls from request thread.

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

What you want is to split Threadpool between short-running and long-running operations. Of course this is not possible with actual implementation of Threadpool and TPL but you can help yourself quite eassilly by writing your own Producer/Consumer queue with awaitable items and customized concurency.

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

Please have a look at example i have put together : https://gist.github.com/3746240

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

Code is copy/pasted from great book "C# 5.0 in a Nutshell: The Definitive Reference" by Joseph Albahari and Ben Albahari with modification done by me causing the scheduler to create dedicated worker threads for items proccesing.

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

#5


0  

As of NHibernate v5, async is now fully supported!

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

Here are some nifty examples:

以下是一些漂亮的例子:

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();

Updating an entity

更新实体

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

来源文章