问题
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.
Here is some article about asynchronous queries in Linq to SQL.
Are any ways to execute Nhibernate query asynchonously? What about Linq to NHibernate?
Thank you, Andrey
回答1:
As of NHibernate v5, async is now fully supported!
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
回答2:
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.
回答3:
multiple async calls can be rewritten with 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.
回答4:
Unfortunately, no. NHibernate does not expose the internal implementation of the command execution in the way L2S does.
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)
回答5:
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.
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.
Please have a look at example i have put together : 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.
来源:https://stackoverflow.com/questions/2485960/how-can-i-run-nhibenate-queries-asynchronously