Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否使用.NET Async/Await对Entity Framework 6.0中的同一数据库进行多次调用?_C#_.net_Sql Server_Entity Framework_Async Await - Fatal编程技术网

C# 是否使用.NET Async/Await对Entity Framework 6.0中的同一数据库进行多次调用?

C# 是否使用.NET Async/Await对Entity Framework 6.0中的同一数据库进行多次调用?,c#,.net,sql-server,entity-framework,async-await,C#,.net,Sql Server,Entity Framework,Async Await,我正在.NET4.7.1上维护一个ASP.NET网站,该网站使用EntityFramework6.0显示一些相当广泛的信息。现在,所有这些DB查询都是以串行方式执行的,所以我试图通过实现async/await来提高性能 我遇到的问题是,对同一个数据库同时运行多个查询似乎有点微妙,我很难找到此类场景的最佳实践 该站点的初始实现为环境事务中的每个查询创建了上下文,并在使用后处理了上下文。在将整个站点转换为使用async时(注意TransactionScopeAsyncFlowOption.Enabl

我正在.NET4.7.1上维护一个ASP.NET网站,该网站使用EntityFramework6.0显示一些相当广泛的信息。现在,所有这些DB查询都是以串行方式执行的,所以我试图通过实现async/await来提高性能

我遇到的问题是,对同一个数据库同时运行多个查询似乎有点微妙,我很难找到此类场景的最佳实践

该站点的初始实现为环境事务中的每个查询创建了上下文,并在使用后处理了上下文。在将整个站点转换为使用async时(注意
TransactionScopeAsyncFlowOption.Enabled
),页面加载开始抛出异常,声称需要配置分布式事务协调器

System.Transactions.TransactionManager通信异常:已禁用分布式事务管理器(MSDTC)的网络访问。
请使用组件服务管理工具在MSDTC的安全配置中为网络访问启用DTC

在这一点上进行的一些搜索使我相信,这可以在代码中纠正,而不会干扰配置,因此我接下来重新设计了数据层,以一种允许连接共享相同上下文的方式来管理连接。但是,在测试该方法时,会抛出新的异常,声称连接太忙

System.Data.SqlClient.SqlException:执行超时已过期。操作完成前已过超时时间,或者服务器没有响应。由于批处理被中止,请求无法运行。这可能是由于从客户端发送的中止信号,或者另一个请求正在同一会话中运行,从而使会话繁忙

通常,此页面的加载时间很慢(几秒钟),但不接近默认超时阈值


async/await是否仅在并行运行的查询连接到不同的数据库时才最适合?如果不是,MSDTC是启用此行为的唯一方法吗?或者,在一个数据库中同时进行这么多查询可能不是一件明智的事情吗?

我无法确切理解您对应用程序所做的更改。我也不确定应用程序一开始写得是否正确,是否遵循了合理的做法。但我希望以下几点数据能有所帮助:

  • EF中的异步支持设计用于在等待I/O时将线程返回池,以便应用程序可以使用较少的线程和资源处理更多的请求。它并不意味着使用相同的DbContext启用并行执行。与.NET中的大多数类型一样,DbContext不是线程安全的(在任何版本的EF中),因此无法在同一上下文实例上安全地并行执行多个查询(异步或非异步)

  • 使用不共享状态或连接对象的单独DbContext实例应该可以,但是建议在ASP.NET中,您在任何时间点都使用单个线程来处理请求(当您进行产生结果的异步调用时,可以在不同的线程上继续处理,但这并不重要)而不是尝试在同一请求中并行工作

  • 另外,关于System.Transaction的例外情况,很可能是您所更改的内容导致多个连接自动登记在同一System.Transactions.Transaction中,这可能需要将事务升级为分布式事务

  • 我不会试图对超时做出完整的解释,因为正如我所说的,我不确定我是否理解您对应用程序所做的更改。但是,如果创建的线程太多,其中一些线程很可能会饿死并超时。如果您从多个线程开始使用非线程安全的类型(例如数据库连接、DbContext),那么很难预测可能出现的所有问题


如果要访问任何重叠的数据,我认为您根本无法共享上下文。不知道MSDTC只是出于好奇,您是在等待调用
ToListSync
之类的东西,还是碰巧只是将代码包装在
任务中。运行
。我不得不问,因为很多人认为后者是进行异步编程的正确方法。这也是为什么至少有一些代码是有帮助的。另外,如果你正确地转换它,它不应该使它更快,或者导致查询并行运行,而以前没有并行运行。异步实际上是在IO发生时释放线程。这在扩展时比在原始性能中有更大的帮助。具体来说,您应该从顶部(webservice端点、事件处理程序)一直到进行IO调用的代码都有异步/等待代码。没有代码很难分辨任何东西。很可能您的实现是错误的。数据库被设计成可以被大量的同时查询摧毁。不需要DTC-您正在使用一个数据库。以任何方式共享EF上下文都是主要的。不,不,永远不要共享它。@b因为在更改之前,您需要先运行query1,然后运行query2,然后运行query3,并且线程一直处于阻塞状态。使用async时,应该是等待查询1,然后等待查询2,然后等待查询3。当每个查询运行时,线程不会被阻塞,但它们不会同时运行(除非您不等待它们,而是捕获任务并等待
任务。whalll
)但是我不知道你在不看代码的情况下在做什么,我只是想知道更多关于这句话的内容——“DbContext不是线程安全的(在任何版本的EF中),因此你不能在同一个上下文上安全地并行执行多个查询(异步或非异步)