27

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

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

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

谢谢你,安德烈

4

5 回答 5

12

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

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

于 2010-10-07T20:36:57.287 回答
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

可以替换为

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 次。

于 2013-09-05T13:56:56.510 回答
9

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

您必须使用线程池或为 NH 创建一个补丁来添加异步查询支持。这会受到社区的欢迎,并且会是一个很好的练习(但这一点也不简单)

于 2010-03-21T20:59:01.823 回答
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();

更新实体

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

来源文章

于 2018-06-23T15:12:37.847 回答
1

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

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

请看一下我整理的示例:https ://gist.github.com/3746240

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

于 2012-09-18T22:17:56.497 回答