问题描述
我已经一年没有编码了,我需要 LinqPad 方面的帮助。我需要运行多个搜索查询才能从我的数据库中获取数据。
假设我需要跑步
void DeepSearch(string input)
{
Orders.Where(y => y.OrderReference.Contains(input)).Dump();
Invoice.Where(y => y.InvoiceReference.Contains(input)).Dump();
Clients.Where(y => y.Name.Contains(input)).Dump();
}
为了提高性能,我想一起启动这 3 个查询,并在得到结果后立即转储。我不在乎顺序。
我可以简单地添加异步吗?
async void DeepSearch(string input)
{
Orders.Where(y => y.OrderReference.Contains(input)).Dump();
Invoice.Where(y => y.InvoiceReference.Contains(input)).Dump();
Clients.Where(y => y.Name.Contains(input)).Dump();
}
解决方法
不,你不能; “异步”与“并行”不同,即使是:数据源需要设计用于(单独)异步和/或并行。我猜测这里的 Orders
、Invoices
和 Clients
是共享数据库连接(可能使用 EF)上的 LINQ 提供程序,在这种情况下:数据库连接在 ADO.NET 中不是为并发/并行而设计的。此外,LINQ 不会直接公开异步操作,但是:EF 确实对异步执行做出了一些让步 - 如果您使用 Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync()
之类的方法,这只是意味着:“将using Microsoft.EntityFrameworkCore;
添加到文件顶部,并使用await source.Where(...).ToListAsync()
”。
然而:
- 异步而不并行不会提高你直接观察到的性能;这只是意味着您在等待数据库时不会占用线程(有限的资源),从而允许释放线程并做比等待更有趣的事情
- 并发很复杂,需要单独的隔离连接(等),或者设计并发的连接
如果您为每个并行操作实例化一个单独的数据上下文,您当然可以并行运行查询。 (这是必需的,因为数据上下文不是线程安全的,无论是 LINQ-to-SQL 还是 EF Core)。
LINQPad 自动生成的数据上下文称为 TypedDataContext
,因此您在 LINQPad 中的代码将如下所示:
Task.Run(() => new TypedDataContext().Orders.Where(y => y.OrderReference.Contains(input)Dump());
Task.Run(() => new TypedDataContext().Invoices.Where(y => y.InvoiceReference.Contains(input)).Dump());
Task.Run(() => new TypedDataContext().Clients.Where(y => y.Name.Contains(input).Dump());
如果将任务分配给变量,则可以等待它们(或使用 Task.WhenAll
等待它们全部)。
根据您使用的是 LINQ-to-SQL 还是 EF Core,还存在与实例化数据上下文相关的成本,因此您可能希望对同一线程上的后续操作重复使用相同的 TypedDataContext。>