针对MS-SQL-Server时Async / Await代码段死锁(正如预期的那样)但在定位Oracle时不会出现死锁(意外)

时间:2017-10-25 11:17:44

标签: sql-server asp.net-mvc oracle entity-framework async-await

前瞻警告:

我完全清楚在下面显示的上下文中使用.Result是错误的,应该不惜一切代价避免使用.Result。我知道正确的方法是什么。

这个问题的本质更多地与db-drivers的基础结构有关:Oracle vs Ms-Sql-Server。这在很大程度上是一个学术问题。

System.Web.MVC.dll: ver. 5.2.3.0 (MVC5)
EntityFramework.dll: ver. 6.1.3
EntityFramework.SqlServer.dll: ver. 6.1.3
Oracle.ManagedDataAccess: ver. 4.121.2.0 (oracle driver ver 12.2.0.1.0)
Oracle.ManagedDataAccess.EntityFramework: ver. 6.121.2.0  (oracle driver ver 12.2.0.1.0)

考虑以下存储库及其在ASP.NET MVC控制器中的调用:

 public class MyRepository {
     [...]
     public async Task<SomeEntity> GetFirstFooAsync() => await new SomeEFContext().FooTable.FirstOrDefaultAsync();
 }

 public class SomeController : Controller {
     public ActionResult SomeAction() {
          var result = new MyRepository.GetFirstFooAsync().Result; //<-- crappy approach I know
          [...]
     }
 }

当底层数据库是Oracle时,上面的代码不会死锁。但是,当通过MS为EF提供的相关驱动程序定位MS-Sql-Server时,这段完全相同的代码会导致死锁。

死锁是这种糟糕代码的预期行为

  • 为什么oracle-driver不会造成死锁?它是在内部使用.ConfigureAwait(false)还是其他一些调整?

  • 如果oracle驱动程序确实使用了调整,我应该担心它可能会产生不良的副作用,即使在适当地编程调用时也是如此

像这样:

 public class SomeController : Controller {
     public async Task<ActionResult> SomeAction() {
          var result = await new MyRepository.GetFirstFooAsync();
          [...]
     }
 }

我之所以这样问,是因为我认为互联网智慧反对使用.ConfigureAwait(false)&#34;部分&#34;因此,我应该在所有其他异步调用(如果有)中使用.ConfigureAwait(false),即使它们针对其他组件。我不确定我是否正确理解/解释上述建议 - 我很乐意予以纠正。如果我有理由担心,请非常友好地提供一个示例,其中部分使用.ConfigureAwait(false)会导致问题,并提供一个示例,说明.ConfigureAwait(false)在多个Async()时的使用方式涉及调用。

2 个答案:

答案 0 :(得分:0)

ConfigureAwait(false)不会阻止这种僵局。

我推测Oracle可能是在Task.Run(或类似的东西)中包含的同步代码异步同步。

ASP.NET Core上不需要

ConfigureAwait(false)(因为它没有同步上下文),不应在action方法中使用,因为在退出action方法后需要上下文。

你可以尝试这个(我没有)看看它是否适用于两个提供者:

public class SomeController : Controller
{
    public ActionResult SomeAction()
    {
        var synchronizationContext = SynchronizationContext.Current;
        try
        {
            var result = new MyRepository.GetFirstFooAsync().Result;
            [...]
        }
        finally
        {
            SynchronizationContext.SetSynchronizationContext(synchronizationContext);
        }
    }
}

答案 1 :(得分:0)

https://community.oracle.com/thread/4092961

胡扯。甲骨文在拉我们的脚。他们对异步/等待没有任何尊重。他们在内部诉诸阻塞呼叫,就好像在任何地方都没有使用异步/等待一样。 “好极了”。