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

发布于 2024-08-11 03:51:19 字数 1241 浏览 1 评论 0原文

我必须对未提交的更改进行查询,并且尝试使用事务,但我发现如果出现异常则不起作用。

我做了一个简单的例子来重现这个问题。 我有一个数据库,只有一个名为“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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

过度放纵 2024-08-18 03:51:19

您确定永远不会调用 scope.Complete() 吗?如果您捕获{}所有异常,代码将继续运行并到达 Complete 语句。相反,您应该让异常传播并在更高级别捕获它。

Are you sure that scope.Complete() is never called? If you catch{} 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.

与君绝 2024-08-18 03:51:19

对于原来的问题来说有点晚了,但也许会对某人有所帮助。

此代码应适用于 .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
    }

}

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.

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
    }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文