异步搜索请求

问题描述

我已经一年没有编码了,我需要 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();
}

解决方法

不,你不能; “异步”与“并行”不同,即使是:数据源需要设计用于(单独)异步和/或并行。我猜测这里的 OrdersInvoicesClients 是共享数据库连接(可能使用 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。>