提高服务器应用程序可伸缩性的一种方法是异步运行IO绑定操作(读取文件,套接字,Web请求,数据库请求等)。这并不意味着在ThreadPool中运行它们,它只会在执行操作时阻塞线程。正确的方法是使用异步API(BeginRead,BeginGetResponse,BeginExecuteReader等)。这个问题在CLR vi C#书中有详细描述。
以下是关于asynchronous queries in Linq to SQL的一些文章。
有任何方法可以异步执行Nhibernate查询吗?怎么样Linq到NHibernate?
谢谢你, 安德烈
答案 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();
}