实体框架 - DbContextTransaction.Rollback()中的问题

时间:2016-12-29 19:02:52

标签: c# sql-server entity-framework transactions rollback

我使用 Entity Framework 连接数据库。我实现了一个联系人存储库来保存联系信息(示例存储库)。在Said类文件中,我声明static property用于处理DBEntities(即BLabsEntities)即“Context”,并为{{static property声明了DbContextTransaction 1}}。

在下面的代码中,我添加了一个try catch块来处理SaveContact() Repository方法中的Entity Framework异常。我在上述方法中启动Save Contact过程之前启动了transaction,然后根据我的想法将dbo.Contact添加到数据库表exception中。在Catch块中,我正在启动所述事务的Rollback进程,我正在尝试在ErrorLog Table中插入Exception消息,但Context属性保存了Contact信息 - 尽管回滚过程执行。 因此,在尝试在dbo.ErrorLog Table 中插入记录时,它会再次在catch块中抛出异常。我添加了一个调试快照供您参考。

C#代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;

namespace EF_Sample
{
    public class ContactRepository
    {
        private static BLabsEntities _context;
        private static DbContextTransaction _dbTransaction;

        protected static BLabsEntities Context
        {
            get { return _context ?? (_context = new BLabsEntities()); }
        }

        protected static DbContextTransaction DBTransaction
        {
            get { return _dbTransaction; }
            set { _dbTransaction = value; }
        }

        public void SaveContact(Contact contact = null)
        {
            try
            {
                if (contact == null)
                {
                    contact = new Contact()
                    {
                        FirstName = null,
                        LastName = null
                    };
                }


                BeginTransaction();
                Context.Contacts.Add(contact);
                Context.SaveChanges();
            }
            catch (Exception ex)
            {
                CommitTransaction(false);

                BeginTransaction();
                ErrorLog error = new ErrorLog()
                {
                    Message = ex.Message
                };

                Context.ErrorLogs.Add(error);

                Context.SaveChanges();
            }
            finally
            {
                CommitTransaction();
            }
        }

        private void BeginTransaction()
        {
            DBTransaction = Context.Database.BeginTransaction();
        }

        private void CommitTransaction(bool flag = true)
        {
            try
            {
                if (flag)
                {
                    DBTransaction.Commit();
                }
                else
                {
                    DBTransaction.Rollback();
                }
            }
            catch (Exception Ex)
            {
                Console.WriteLine("Error: {0}", Ex.Message);
            }
        }
    }
}

调试快照:

enter image description here

try Block中的异常:代码明确创建的异常

enter image description here

Catch Block中的例外:Rollback操作失败

enter image description here

数据库表结构:

enter image description here

请帮助我成功完成Rollback操作,以清除上下文更改

1 个答案:

答案 0 :(得分:1)

实际答案可能更简单:

https://github.com/aspnet/EntityFramework.Docs/issues/327

在大多数情况下,无需显式调用dbContextTransaction.Rollback(),因为在using块末尾放置事务将有助于回滚。

  

如果SQL Server中发生足够严重的错误,则   交易将自动回滚,并且对   catch块中的dbContextTransaction.Rollback()实际上会失败。