【EF Core】三种事务(SaveChange、DBContextTransaction、TransactionScope)

EF中的事务主要分为三类,分别是SaveChangesDbContextTransactionTransactionScope

SaveChanges

SaveChanges一次性将本地缓存中所有的状态变化一次性提交到数据库,这就是一个事务,要么统一成功,要么统一回滚。
使用场景:一个DBContext,即一个数据库的EF的上下文,不能控制多个数据库。

DbContextTransaction事务

通常用于手动接管事务,某些操作是一个事务,某些操作是另外一个事务。
使用场景:EF调用SQL语句的时候使用该事务、 多个SaveChanges;不同控制多个数据库

private static void TestDbContextTransactionFailure()
{
    using (DbContext db = new CodeFirstModel())
    {
        DbContextTransaction trans = null;
        try
        {
            //开启事务
            trans = db.Database.BeginTransaction();
            //增加
            string sql1 = @"insert into TestInfor  values(@id,@txt1,@txt2)";
            SqlParameter[] pars1 ={
                                         new SqlParameter("@id",Guid.NewGuid().ToString("N")),
                                         new SqlParameter("@txt1","txt11"),
                                         new SqlParameter("@txt2","txt22")
                                    };
            db.Database.ExecuteSqlCommand(sql1, pars1);
            //修改
            string sql3 = @"update TestInfor set txt1=@txt1 where id=@id";
            SqlParameter[] pars3 ={
                                         new SqlParameter("@id","3"),
                                         new SqlParameter("@txt1","二狗子222")
                                    };
            db.Database.ExecuteSqlCommand(sql3, pars3);

            //提交事务
            trans.Commit();
            Console.WriteLine("事务成功了");
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            trans.Rollback();

        }
        finally
        {
            trans.Dispose();
        }
    }
}

TransactionScope事务

该事务用来处理多个SaveChanges的事务(特殊情况的业务)或者多个DBContext(每个DBContext是一个实例,代表不同的数据库连接).
如果使用该事务来处理多个数据库(多个DBContex)时,必须手动开启msdtc服务,这样才可以将多个DB的SaveChange给放到一个事务中
使用场景:

  • 多数据库连接的情况
  • 主键id自增的情况,同一个业务线中,需要拿到新增加的数据的主键id,进行操作。

主键自增被使用的情况的解决方案

private static void Test3()
        {
            using (DbContext db = new CodeFirstModel())
            {
                using (TransactionScope trans = new TransactionScope())
                {
                    try
                    {
                        TestInfor2 t1 = new TestInfor2()
                        {
                            txt11 = Guid.NewGuid().ToString("N"),
                            txt22 = Guid.NewGuid().ToString("N")
                        };
                        db.Set<TestInfor2>().Add(t1);
                        //如果这里不写SaveChanges的话,t1.id永远为0
                        db.SaveChanges();


                        TestInfor2 t2 = new TestInfor2()
                        {
                            txt11 = (t1.id + 1).ToString(),
                            txt22 = Guid.NewGuid().ToString("N")
                        };
                        db.Entry(t2).State = EntityState.Added;
                        db.SaveChanges();

                        //事务统一提交(若失败则统一回滚)
                        trans.Complete();
                        Console.WriteLine("自增提交成功");
                    }
                    catch (Exception)
                    {
                        Transaction.Current.Rollback();
                    }
                }
            }
        }

多个DBContext、多个数据库的情况。

private static void TransactionScopeTwoDB()
        {
            using (TransactionScope trans = new TransactionScope())
            {
                try
                {
                    DbContext db1 = new CodeFirstModel();
                    DbContext db2 = new CodeFirstModel2();
                    //数据库1
                    TestInfor t1 = new TestInfor()
                    {
                        id = Guid.NewGuid().ToString("N"),
                        txt1 = "111111111",
                        txt2 = "222222222222"
                    };
                    db1.Entry(t1).State = EntityState.Added;
                    db1.SaveChanges();

                    //数据库2
                    TestOne t2 = new TestOne()
                    {
                        id = Guid.NewGuid().ToString("N"),    //可以在此处手动制造个错误,来测试多数据库的回滚问题
                        t1 = "222",
                        t2 = "2222"
                    };
                    db2.Entry(t2).State = EntityState.Added;
                    db2.SaveChanges();

                    trans.Complete();
                    Console.WriteLine("多个数据库添加成功");
                }
                catch (Exception)
                {
                    Transaction.Current.Rollback();
                }

            }
        }
posted @ 2022-05-22 00:35  .Neterr  阅读(1455)  评论(0编辑  收藏  举报