C# 消失的EF呼叫之谜

C# 消失的EF呼叫之谜,c#,asp.net-mvc-4,iis-7,entity-framework-5,C#,Asp.net Mvc 4,Iis 7,Entity Framework 5,今天我接到ASP.NET生产系统用户的紧急电话。某些用户(并非全部)无法输入某些数据。用户发布了数据,然后系统冻结;电话再也没有回过 我们试图在QA系统上重新处理这个问题(该系统有一个新的生产数据恢复),但没有成功。然后,我从我的开发环境运行,并直接连接到生产数据库,伪装成受影响的用户之一。再说一次,没问题。结论:生产环境中一定存在某种问题,可能是在托管网站的IIS进程中的某个地方 因此,我在生产服务器上启动了Visual Studio,并连接到IIS进程(孩子们,不要在家里这么做!),在有问题

今天我接到ASP.NET生产系统用户的紧急电话。某些用户(并非全部)无法输入某些数据。用户发布了数据,然后系统冻结;电话再也没有回过

我们试图在QA系统上重新处理这个问题(该系统有一个新的生产数据恢复),但没有成功。然后,我从我的开发环境运行,并直接连接到生产数据库,伪装成受影响的用户之一。再说一次,没问题。结论:生产环境中一定存在某种问题,可能是在托管网站的IIS进程中的某个地方

因此,我在生产服务器上启动了Visual Studio,并连接到IIS进程(孩子们,不要在家里这么做!),在有问题的代码中设置断点,以用户身份登录,并尝试保存数据。点击断点并逐行执行,直到我点击一行这样的代码:

try
{
  ...
  using (var db = new MyDataContext())
  {
    ...
    var fooToUpdate = db.Foos.Single(f => f.ID == fooId); // <-- THIS LINE
    ...
  }
}
catch (Exception ex)
{
  // some error logging
}
试试看
{
...
使用(var db=new MyDataContext())
{
...

var fooToUpdate=db.Foos.Single(f=>f.ID==fooId);//鉴于线程没有神奇地蒸发,我们可以推测一些更可能的选项:

  • 调试器很难跟踪在发布模式下编译的生产代码。仅仅因为调试发布代码90%的时间都在工作,不要误以为它是可靠的。优化的代码可以很快使调试器偏离实际执行的轨道。当这种情况发生时,它看起来就像线程刚刚消失一样。
  • 假设线程确实合法地进入调用而不返回(应用程序“冻结”的原始投诉似乎支持这一点),则最有可能的情况是某种类型的死锁。
    EntityFramework
    死锁并不常见,但也并非闻所未闻。我所知道的最常见的问题通常涉及
    TransactionScope
    CommitteeTransaction
    。您是否在省略的代码部分使用任何事务

  • 事实证明,EF部分毕竟是一条红鲱鱼。我去下载了Telerik的JustDecompile和JustCode,希望进入EF代码,但当我进入这一行时,我发现自己不在
    单()
    extension方法,但在我自己的一个方法调用中—我认为我在前一行中执行了该方法。显然,代码与生产中的版本并不完全同步

    第1课:如果您附加到一个进程,如果您的代码与之前的代码不同,那么您的执行点可能不在您认为的位置 在这个过程中被编译

    所以不管怎样,现在我可以不用反编译任何东西就直接进入代码,我注意到的第一件事是:

    lock (_lockObj)
    {
      ...
    }
    
    当我试图进入它时,它冻结在那里。冒烟的枪

    因此,在某个地方,其他线程正在锁定该对象。查看调用锁的其他地方,会导致大量依赖项,以及另一个代码锁定段,有几个DB调用,甚至一个事务边界。这可能是代码锁/DB事务死锁,尽管对DB transactio中的代码进行了简短扫描n未能在事务生命周期内找到任何竞争者来阻止任何其他事务。此外,有证据表明DB没有显示任何阻止或打开的事务。相反,这可能只是数百个排队的长期运行进程的事实,所有的内部代码锁都在代码锁中,最后看起来都有些问题就像周五17:05的西侧公路一样,一辆自升式拖车横跨3条车道,接近GW大桥

    第2课:当与DB事务一起使用时,代码锁不仅是危险的,而且尤其是危险的。尝试找到不使用代码锁的方法来确保代码线程的安全。如果您确实必须使用代码锁,请确保您尽快进出。不要给您的线程一本杂志来阅读可以说,他占据了唯一的摊位


    在该方法的其他地方存在事务边界,但我们在该执行点不在事务边界内。从技术上讲,死锁场景也可能由访问
    EntityFramework
    的任何其他应用程序线程启动。您可能希望在线搜索各种检测死锁的方法,以看看这是否是一个可能的罪魁祸首。但在调用数据库时未记录任何调用,因为数据库可能会发生死锁。问题发生在执行到达数据库之前。死锁可能没有发生在SQL Server中。有时,来自关键节的死锁会挂起在e surface,完全不相关。这可能是需要在WinDbg/SOS中检查内存转储的问题之一。如果您这样做,请从
    !analyze-hang-v
    命令开始。我想我已经解决了。请参阅我的答案。+1感谢您的逻辑和有用的评论。谢谢!您尝试在prod上查看事件查看器了吗是否有任何有意义的信息(如有)?