简体   繁体   English

无法使用实体框架回滚事务

[英]Cannot rollback transaction with Entity Framework

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. 我有一个只有一个名为“ Tabella”的表的数据库,该表有两个字段:“ ID”是自动生成的整数,而“ Valore”是具有唯一约束的整数。 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. 一种是Valore = 1,另一种是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). 似乎第二次调用SaveChanges方法回滚了自己的更改并“删除”了该事务,然后第三次调用SaveChanges提交了第一个和第三个插入的更改(这时好像该事务不存在)。

I also tried to use SaveChanges(false) method (even without calling AcceptAllChanges method), but with no success: I have the same behaviour. 我也尝试使用SaveChanges(false)方法(即使不调用AcceptAllChanges方法),但都没有成功:我有相同的行为。

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. 我不希望事务由SaveChanges自动回滚,因为我想更正错误(例如,通过catch语句中的用户交互)并重试。

Can someone help me with this? 有人可以帮我弄这个吗? It seems like a "bug", and it is giving me a really big headache... 看起来像个“虫子”,这让我非常头痛。

Are you sure that scope.Complete() is never called? 您确定从未调用scope.Complete()吗? If you catch{} all exceptions, the code will continue running and the Complete statement will be reached. 如果您catch{}所有异常,则代码将继续运行并到达Complete语句。 Instead, you should for example let the exception to propagate and catch it at a higher level. 相反,您应该例如让异常传播并在更高级别捕获它。

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. 此代码应与.net / ef 4和sql server 2008 R2一起使用。

using (TransactionScope scope = new TransactionScope())
{
    Db1Container db1 = new Db1Container();

    try
    {
        db1.AddToTabella(new Tabella()
        {
            Valore = 1
        });
        db1.SaveChanges();

        db1.AddToTabella(new Tabella()
        {
            Valore = 1
        });
        db1.SaveChanges(); //Unique constraint is violated here and an exception is thrown

        //if we get here then there were no errors thrown on previous SaveChanges() 
        //calls and we can complete the transaction with no rollback
        scope.Complete();

    }
    catch (Exception)
    {
        //do nothing
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM