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了!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM