程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> ADO.NET Entity Framework深入分析,Part 6–處理並發(Concurrency Handling)

ADO.NET Entity Framework深入分析,Part 6–處理並發(Concurrency Handling)

編輯:關於.NET

設置並發模式

Entity Framework 實現了樂觀的並發模式(Optimistic Concurrency Model)。默認情況下,在實體更新數據提交到數據庫時,並不會檢查並發。對於高頻率的並發屬性,你需要設置屬性的並發模式為Fixed。

這些屬性將會加入到T-SQL腳本的WHERE子句部分,用來比較客戶端的值和數據庫端的值。

示例代碼:

public void UpdateProduct()
{
 Product product = context.Product.FirstOrDefault(p => p.ProductID == 1004);
 if (product != null)
 {
  product.Color = "White";
  product.StandardCost = 200;
  product.ListPrice = 250;
 }
 context.SaveChanges();
}

正常情況下,不檢查並發情況,產生的T-SQL腳本如下:

exec sp_executesql N'update [SalesLT].[Product]
set [Color] = @0, [StandardCost] = @1, [ListPrice] = @2
where ([ProductID] = @3)',
N'@0 nvarchar(5), @1 decimal(19,4), @2 decimal(19,4), @3 int', @0=N'White', @1=1000.0000, @2=2000.0000,@3=1004

在設置Product實體的Color屬性的Concurrency Mode 為Fixed,你會發現生成的T-SQL腳本中,Where子句中增加了對Color 字段的檢查:

exec sp_executesql N'update [SalesLT].[Product]
set [Color] = @0, [StandardCost] = @1, [ListPrice] = @2
where (([ProductID] = @3) and ([Color] = @4))',
N'@0 nvarchar(5), @1 decimal(19,4), @2 decimal(19,4), @3 int, @4 nvarchar(5)', @0=N'White', @1=200.0000, @2=250.0000, @3=1004, @4=N'White'

解決並發沖突

如下的示例代碼演示如何解決並發沖突。當發生並發沖突時,將拋出OptimisticConcurrencyException 異常,可以通過調用Object Context 的Refresh() 方法,傳入RefreshMode.ClientsWins 選項,來解決沖突。這將重新執行LINQ to Entities 查詢,並覆蓋數據庫的值,隨後再次調用SaveChanges() 方法。

模擬並發沖突及其腳本:

public void UpdateProduct()
{
 Product product1 = context.Product.FirstOrDefault(p => p.ProductID == 1004);
 if (product1 != null)
 {
  product1.Color = "Black";
  product1.StandardCost = 20;
  product1.ListPrice = 25;
 }

 AdventureWorksLTEntities context2 = new AdventureWorksLTEntities();
 Product product2 = context2.Product.FirstOrDefault(p => p.ProductID == 1004);
 if (product2 != null)
 {
  product2.Color = "Blue";
  product2.StandardCost = 18;
  product2.ListPrice = 30;
 }

 // Save changes of first DataContext
 context.SaveChanges();

 try
 {
  context2.SaveChanges();
 }
 catch (OptimisticConcurrencyException ex)
 {
  Console.WriteLine(ex.ToString());
  // The concurrently conflict can be resolved by refreshing the DataContext
  context2.Refresh(RefreshMode.ClientWins, product2);
  // And saving the changes again
  context2.SaveChanges();

 }
}

Refresh的第一個參數值得注意一下,它是一個枚舉值,有兩個選項:StoreWins或者是ClientWins。如果是StoreWins,那麼,Refresh以後,product2的值將與數據庫裡的對應記錄的值一致(修改會丟失);而如果ClientWins,則product2的值保持,並且提交以後,會把context提交的修改覆蓋。

其實,這兩種方法均不完美,總會導致一部分修改丟失。但是,這總比在不知情的情況下的覆蓋要好。 另外,需要說明,上面的方法,只是對並發沖突的一種模擬,這樣的模式,在處理並發沖突時會有問題。一般的處理方法是,當檢測到並發沖突時,提示用戶會重新從數據庫載入數據,然後,讓用戶在新數據的情況下重新修改後再次提交,直到不再有並發沖突發生。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved