EF中关于TransactionScope的使用

前提条件

 

TransactionScope类需要引用System.Transactions;

 

 

数据库环境及需求

现在假设有两个表如图:

                                      

 

 

           表TA                                                                                  表TB 

 

 

现有数据:                                            

 

 

 

 

 

 现在的需求是:每往TA中插入一条数据,就更新TB的第一行,值为表TA的所有行的Age的平均值

 可以看到表TB的Remark长度仅仅为2,待会利用这个制造错误

 

 

 

当不使用TransactionScope时:

 using (EFTestEntities db = new EFTestEntities())
            {
                //数据库TA原有2行,此时添加第3行
                var aEntity = new TA
                {
                    Name = "a",
                    Age = 20
                };
                db.TA.Add(aEntity);

                var listTA = db.TA.ToList();//此时list只有2行,新添加的没有读取到
                int totalAge = 0;
                listTA.ForEach(p => totalAge += p.Age);

                //获取表TB的第一行,并修改AvgAge值
                var bEntity = db.TB.First();
                bEntity.AvgAge = totalAge / listTA.Count;
                bEntity.Remark = "bb";
                db.SaveChanges();
                //结果是Tb的值没有变化
            }  
View Code

 

你认为是添加TA后没有db.SaveChanges();? 的确,添加这个之后,可以读取到新添加的值了,但是没有事务了,如:

 

using (EFTestEntities db = new EFTestEntities())
            {
                //数据库TA原有2行,此时添加第3行
                var aEntity = new TA
                {
                    Name = "a",
                    Age = 20
                };
                db.TA.Add(aEntity);
                db.SaveChanges();

                var listTA = db.TA.ToList();//此时list有3行了,新添加的可以被读取到
                int totalAge = 0;
                listTA.ForEach(p => totalAge += p.Age);

                //获取表TB的第一行,并修改AvgAge值
                var bEntity = db.TB.First();
                bEntity.AvgAge = totalAge / listTA.Count;
                bEntity.Remark = "bbc";//故意超出长度,制造错误
                db.SaveChanges();
                //结果是TA添加了新行,但是TB修改时出错导致修改失败。造成了数据不一致
            }  
View Code

 

结果是TA添加了新行,但是TB因为remark超出长度导致导致修改失败,此时TB的数据是错的。

 

怎样可以避免这个问题?答案就是用事务。

 

使用TransactionScope:

 

using (EFTestEntities db = new EFTestEntities())
            {
                using (TransactionScope ts = new TransactionScope())
                {
                    //数据库TA原有2行,此时添加第3行
                    var aEntity = new TA
                    {
                        Name = "a",
                        Age = 20
                    };
                    db.TA.Add(aEntity);
                    db.SaveChanges();//重点,必须要db.SaveChanges(),然后下面才能获取到新添加的行

                    var listTA = db.TA.ToList();//此时list有3行了,新添加的可以被读取到
                    int totalAge = 0;
                    listTA.ForEach(p => totalAge += p.Age);

                    //获取表TB的第一行,并修改AvgAge值
                    var bEntity = db.TB.First();
                    bEntity.AvgAge = totalAge / listTA.Count;
                    bEntity.Remark = "bbc";//故意超出长度,制造错误
                    db.SaveChanges(); //执行到此处程序报错

                    ts.Complete();//事务提交未执行
                    //结果是自动回滚,相当于此次没有对数据库做任何操作。保持了数据一致性
                }
            }
View Code

 

 下面给出正确的示例,实现以上需求:

using (EFTestEntities db = new EFTestEntities())
            {
                using (TransactionScope ts = new TransactionScope())
                {
                    //数据库TA原有2行,此时添加第3行
                    var aEntity = new TA
                    {
                        Name = "a",
                        Age = 20
                    };
                    db.TA.Add(aEntity);
                    db.SaveChanges();//重点,必须要db.SaveChanges(),然后下面才能获取到新添加的行

                    var listTA = db.TA.ToList();//此时list有3行了,新添加的可以被读取到
                    int totalAge = 0;
                    listTA.ForEach(p => totalAge += p.Age);

                    //获取表TB的第一行,并修改AvgAge值
                    var bEntity = db.TB.First();
                    bEntity.AvgAge = totalAge / listTA.Count;
                    bEntity.Remark = "bb";//数据符合规范
                    db.SaveChanges(); //保存

                    ts.Complete();//提交事务
                    //结果是执行成功,TA多一条数据,同时TB的值也变了
                }
            }
View Code

 

 

一切都nice了!

 

转载于:https://www.cnblogs.com/dengshaojun/p/5761013.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值