1. 程式人生 > >Linq to Sql學習總結5

Linq to Sql學習總結5

修改併發異常ChangeConfictException

//測試修改併發異常ChangeConfictException
            var query = from p in ctx.Products
                        where p.CategoryID == 1
                        select p;
            foreach (var p in query)
            {
                p.UnitsInStock = Convert.ToInt16(p.UnitsInStock - 1
); } ctx.SubmitChanges();// 在這裡設斷點,程式執行到此處時,在資料庫執行如下T_SQL操作 /* UPDATE dbo.Products SET UnitsInStock = UnitsInStock - 2 WHERE CategoryID=1 */ //然後繼續執行程式,會丟擲修改併發異常ChangeConfictException /* 原因分析:當客戶端提交的修改物件自讀取之後已經在資料庫中發生改動,就產生了修改併發。*/ /*
不考慮併發修改異常設定:實體類屬性column特性增加UpdateCheck = UpdateCheck.Never * 不考慮併發修改異常情況下,預設是最後一次更新起作用 */

處理修改併發異常ChangeConfictException

//處理修改併發異常ChangeConfictException
            var query = from p in ctx.Products
                        where p.ProductID == 1
                        select
p; foreach (var p in query) { p.UnitsInStock = Convert.ToInt16(p.UnitsInStock - 1); } try { ctx.SubmitChanges(ConflictMode.ContinueOnConflict); } catch (ChangeConflictException) { foreach (ObjectChangeConflict cc in ctx.ChangeConflicts) { Products product = (Products)cc.Object; cc.Resolve(RefreshMode.OverwriteCurrentValues);// 放棄當前程序更新,所有更新以原先其它程序更新為準 //cc.Resolve(RefreshMode.KeepCurrentValues); // 放棄原先其它程序更新,所有更新以當前程序更新為準 //cc.Resolve(RefreshMode.KeepChanges); // 原先其它程序更新有效,衝突欄位以當前程序更新為準 } } ctx.SubmitChanges();
//針對不同策略處理不同欄位修改併發異常ChangeConfictException
            var query = from p in ctx.Products
                        where p.ProductID == 1
                        select p;
            foreach (var p in query)
            {
                p.UnitsInStock = Convert.ToInt16(p.UnitsInStock - 1);
            }
            try
            {
                ctx.SubmitChanges(ConflictMode.ContinueOnConflict);
            }
            catch (ChangeConflictException)
            {
                //遍歷併發衝突物件集合
                foreach (ObjectChangeConflict cc in ctx.ChangeConflicts)
                { 
                    //遍歷當前衝突物件更新失敗的成員(即更新失敗的列)
                    foreach (MemberChangeConflict mc in cc.MemberConflicts)
                    {
                        if (mc.Member.Name == "UnitsInStock")
                        {
                            mc.Resolve(RefreshMode.KeepCurrentValues); // 放棄原先其它程序更新,所有更新以當前程序更新為準
                        }
                        else if (mc.Member.Name == "UnitPrice")
                        {
                            mc.Resolve(RefreshMode.OverwriteCurrentValues); // 放棄當前程序更新,所有更新以原先其它程序更新為準
                        }
                        else
                        {
                            mc.Resolve(RefreshMode.KeepChanges); // 原先其它程序更新有效,衝突欄位以當前程序更新為準
                        }
                    }
                }
            }

            ctx.SubmitChanges();

事務:

//Linq to sql在提交更新的時候預設會建立事務,一部分修改發生錯誤的話其它修改也不會生效:
            //假設資料庫中已經存在顧客ID為“ALFKI”的記錄,那麼第二次插入操作失敗將會導致第一次的插入操作失效。
            ctx.Customers.InsertOnSubmit(new Customers { CustomerID = "abcdf", CompanyName = "zhuye" });
            ctx.Customers.InsertOnSubmit(new Customers { CustomerID = "ALFKI", CompanyName = "zhuye" });
            ctx.SubmitChanges();

使用事務

            ctx.Connection.Open();
            ctx.Transaction = ctx.Connection.BeginTransaction();
            ctx.Customers.InsertOnSubmit(new Customers { CustomerID = "abcdf", CompanyName = "zhuye" });
            ctx.Customers.InsertOnSubmit(new Customers { CustomerID = "ALFKI", CompanyName = "zhuye" });
            try
            {
                ctx.SubmitChanges();
                ctx.Transaction.Commit();
            }
            catch
            {
                ctx.Transaction.Rollback();
            }
            ctx.Connection.Close();

使用TransactionScope

            using (TransactionScope tranScope = new TransactionScope())
            {
                ctx.Customers.InsertOnSubmit(new Customers { CustomerID = "abcdf", CompanyName = "zhuye" });
                ctx.Customers.InsertOnSubmit(new Customers { CustomerID = "ALFKI", CompanyName = "zhuye" });
                tranScope.Complete();
            }