无法使用实体框架回滚事务
我必须对未提交的更改进行查询,并且尝试使用事务,但我发现如果出现异常则不起作用。
我做了一个简单的例子来重现这个问题。 我有一个数据库,只有一个名为“Tabella”的表,该表有两个字段:“ID”是一个自动生成的整数,“Valore”是一个具有唯一约束的整数。然后我尝试运行此代码:
using (TransactionScope scope = new TransactionScope())
{
Db1Container db1 = new Db1Container();
try
{
db1.AddToTabella(new Tabella()
{
Valore = 1
});
db1.SaveChanges();
}
catch { }
try
{
db1.AddToTabella(new Tabella()
{
Valore = 1
});
db1.SaveChanges(); //Unique constraint is violated here and an exception is thrown
}
catch { }
try
{
db1.AddToTabella(new Tabella()
{
Valore = 2
});
db1.SaveChanges();
}
catch { }
//scope.Complete(); //NEVER called
} //here everything should be rolled back
现在,如果我查看数据库,它应该不包含任何记录,因为事务应该回滚,相反,我找到了两条记录!一种是 Valore=1,另一种是 Valore=2。 我缺少什么吗?看起来第二次调用 SaveChanges 方法回滚了自己的更改并“删除”了事务,然后第三次调用 SaveChanges 提交了第一次和第三次插入的更改(此时就像事务不存在一样)。
我还尝试使用 SaveChanges(false) 方法(即使不调用 AcceptAllChanges 方法),但没有成功:我有相同的行为。
我不希望 SaveChanges 自动回滚事务,因为我想更正错误(例如通过 catch 语句中的用户交互)并重试。
有人可以帮我解决这个问题吗?这看起来像是一个“bug”,这让我非常头疼......
I have to do queries on uncommitted changes and I tried to use transactions, but I found that it do not work if there are exceptions.
I made a simple example to reproduce the problem.
I have a database with only one table called "Tabella" and the table has two fields: "ID" is a autogenerated integer, and "Valore" is an integer with a Unique constraint. Then I try to run this code:
using (TransactionScope scope = new TransactionScope())
{
Db1Container db1 = new Db1Container();
try
{
db1.AddToTabella(new Tabella()
{
Valore = 1
});
db1.SaveChanges();
}
catch { }
try
{
db1.AddToTabella(new Tabella()
{
Valore = 1
});
db1.SaveChanges(); //Unique constraint is violated here and an exception is thrown
}
catch { }
try
{
db1.AddToTabella(new Tabella()
{
Valore = 2
});
db1.SaveChanges();
}
catch { }
//scope.Complete(); //NEVER called
} //here everything should be rolled back
Now if I look into the database it should contain no records because the transaction should rollback, instead I find two records!!!! One with Valore=1 and one with Valore=2.
I am missing something? It looks like the second call to SaveChanges method rollback its own changes and "deletes" the transaction, then the third call to SaveChanges commits the changes of the first and the third insert (at this point it is like the transaction not exists).
I also tried to use SaveChanges(false) method (even without calling AcceptAllChanges method), but with no success: I have the same behaviour.
I do not want the transaction to be rolled back automatically by SaveChanges, because I want to correct the errors (for example by user interaction in the catch statement) and make a retry.
Can someone help me with this? It seems like a "bug", and it is giving me a really big headache...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您确定永远不会调用
scope.Complete()
吗?如果您捕获{}
所有异常,代码将继续运行并到达 Complete 语句。相反,您应该让异常传播并在更高级别捕获它。Are you sure that
scope.Complete()
is never called? If youcatch{}
all exceptions, the code will continue running and the Complete statement will be reached. Instead, you should for example let the exception to propagate and catch it at a higher level.对于原来的问题来说有点晚了,但也许会对某人有所帮助。
此代码应适用于 .net/ef 4 和 sql server 2008 R2。
This is a bit late for the original question but perhaps it will help someone.
This code should work with .net/ef 4 and sql server 2008 R2.