首页 > 其他分享 >【EF Core】三种事务(SaveChange、DBContextTransaction、TransactionScope)

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

时间:2022-11-02 16:25:23浏览次数:89  
标签:Core 事务 数据库 EF db SaveChanges DBContextTransaction new id

原文网址:https://www.cnblogs.com/fanfan-90/p/16296737.html

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();
                }

            }
        }
事务的四个特性
原文网址:https://baijiahao.baidu.com/s?id=1717564719318727121



答:原子性、一致性、隔离性、持久性

 

原子性事务中的操作为一个整体,要么都做,要么都不做.即一旦事务出错,就回滚事务

 

一致性事务:执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。

 

如果数据库系统 运行中发生故障,有些事务尚未完成就被迫中断,这些未完成事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处于一种不正确的状态,或者说是 不一致的状态。

 

隔离性:一个事务的执行不能被其他事务干扰。即一个事物内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事物之间不能互相干扰

 

持久性:指一个事物一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响

 

事务:是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作;这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合(工作逻辑单元)

 

标签:Core,事务,数据库,EF,db,SaveChanges,DBContextTransaction,new,id
From: https://www.cnblogs.com/bruce1992/p/16851396.html

相关文章

  • .Net Core验证码
    1、复制下列代码,拷贝到控制器中。#region生成验证码图片//[OutputCache(Location=OutputCacheLocation.None,Duration=0,NoStore=false)]......
  • CF487C Prefix Product Sequence
    CF487CPrefixProductSequence一道妙哉的构造题。首先有两点很明显:\(1\)一定在第一个,\(n\)一定在最后一个。除了\(4\)的合数都无解(\(1\)特判)根据题解第......
  • mysql——left join on and和left join on where的区别
    参考https://www.cnblogs.com/cgsdg/p/16426658.html 总结:and条件语句不会剔除不满足条件的左表的行。where条件语句会剔除。   ......
  • js的True is not defined以及c#的未将对象引用设置到对象的实例问题
    C#的true传到javascript变为TrueC#:varvoted=empfinal.Count()>0?true:false;JS:if(@voted){alert("您已经投过票了!");return;}报错:Trueisnot......
  • Makefile中:=,=,+=,?=
    #=等号取终值,所以B=4A=1B=2C=$(A)_$(B)B=4$(warning$(C))#C的定义是引用传递所以C=1_4, #:=取的是他前面定义的值(即取初始值,如果后面变量在变化,还是取最开始定义......
  • Codeforces Round #611 (Div. 3) E
    E.NewYearParties对于最大值我们显然可以sort之后贪心一下即可正确性显然对于最小值我们发现会有三种情况一种是三个挨在一起一种是两个挨在一起还有一种就是......
  • 深入浅出ASP .NET Core学习记录
    深入浅出ASP.NETCore学习记录《深入浅出》第二部分总结第二章的学习代码:代码概括主要是实操,下面是实操完的项目结构图几个文件夹,代表什么意思Controllers(重......
  • 【Android】SwipeRefreshLayout的简单使用教程。下拉刷新控件炫酷效果。
    作者:程序员小冰,GitHub主页:​​https://github.com/QQ986945193​​新浪微博:​​http://weibo.com/mcxiaobing​​首先给大家看一下我们今天这个最终实现的效果图:好了,简......
  • Jmeter启动报错: ANOMALY: use of REX.w is meaningless (default operand size is 64
    摘要:需要远程到其他电脑,把本机的jmeter打包发到远程的电脑上,启动jmeter时报错如下:  原因分析:第一反应无法创建java虚拟机我以为是没有JDK,通过CMD  Java-version......
  • .Net Core后台任务启停(BackgroundService)
    BackgroundService描述说明:BackgroundService类 说到定时任务,可能第一个会想到Quartz,但是想到需要更简洁,而且想要毫秒级的周期,这个Cron真是太不智慧了,虽说可以在单个......