上次查询引发异常时的死锁

时间:2015-03-02 17:04:55

标签: c# sql-server entity-framework

使用实体框架,我有一个基本上是这样的函数:

using (var ctx = new Dal.MyEntities())
{
    try
    {
        //...
        // create a temp entity
        Dal.Temp temp = new Dal.Temp();
        // populate its children
        // note that temp is set to cascade deletes down to it's children
        temp.Children = from foo in foos
                        select new Dal.Children()
                        {
                            // set some properties...
                            Field1 = foo.field1,
                            Field2 = foo.field2
                        }
        //...
        // add temp row to temp table
        ctx.Temp.Add(temp);
        ctx.SaveChanges();
        // some query that joins on the temp table...
        var results = from d in ctx.SomeOtherTable
                      join t in temp.Children
                      on new { d.Field1, d.Field2 } equals new { t.Field1, d.Field2 }
                      select d;
        if (results.Count() == 0)
        {
            throw new Exception("no results")
        }
        // Normal processing and return result
        return results;
    }
    finally
    {
        if (temp != null && temp.ID != 0)
        {
            ctx.TempTables.Remove(temp);
            ctx.SaveChanges();
        }
    } 
}

我的想法是,作为处理请求的一部分,我需要构建一个包含一些数据的临时表,然后将其用于加入主查询并过滤结果。处理完查询后,应删除临时表。我将删除部分放在finally子句中,这样如果查询出现问题(抛出异常),临时表将始终被清除。

这似乎工作正常,除了间歇性我有一个问题是SaveChanges块中的finally引发了一个死锁异常,并带有错误消息:

Transaction (Process ID 89) was deadlocked on lock resources with another process and 
has been chosen as the deadlock victim. Rerun the transaction.

我无法可靠地重现它,但如果之前的查询抛出“无结果”异常,它似乎最常发生。请注意,由于在前端发现的错误,在某些情况下提交了两个相同的请求,但是,代码应该能够处理它。

有没有人知道这里可能发生的事情?在using块内抛出异常会出现问题吗?我应该区别对待吗?

更新,所以异常可能是红鲱鱼。我完全删除它(而不是返回一个空的结果),我仍然有问题。我尝试了很多变种:

using (new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.ReadUncommitted })
using (var ctx = new Dal.MyEntities())
{

}

但是尽管我已经阅读过,但它似乎没有任何区别。我仍然在第二个SaveChanges上获得间歇性死锁以删除临时表。

1 个答案:

答案 0 :(得分:0)

如何添加

using (var ctx = new Dal.MyEntities())
{
    try
    {
        //...
        Dal.TempTable temp = new Dal.TempTable();
        //...
        ctx.TempTables.Add(temp);
        // some query that joins on the temp table...
        if (no
        results are 
        returned)
        {
            throw new Exception("no results") 
        }
        // Normal processing and return result
    }
    catch
    {
        ctx.TempTables.Remove(temp);
        ctx.SaveChanges();
    }
    finally
    {
        if (temp != null && temp.ID != 0)
        {
            ctx.TempTables.Remove(temp);
            ctx.SaveChanges();
        }
    }
}