使用实体框架,我有一个基本上是这样的函数:
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
上获得间歇性死锁以删除临时表。
答案 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();
}
}
}