程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 在Linq to Sql中管理並發更新時的沖突(1) 預備知識

在Linq to Sql中管理並發更新時的沖突(1) 預備知識

編輯:關於.NET

無論與目前的ORM框架相比有沒有優勢,Linq to Sql在語言和平台的級別上 為我們提供了一種新的操作對象和數據的方式,在一定程度上為我們解決了 Object != Data的問題。在實際應用中,對於數據庫的操作往往有著天生的並發 性,因此在更新數據時可能會產生沖突。有些時候,如果沒有合理的解決沖突問 題,輕則讓用戶摸不著頭腦,重則讓系統數據處於一種不一致的狀態。Linq to Sql自然考慮到了這一點,本系列討論的內容,就是在使用Linq to Sql時,如何 管理並發更新時產生的沖突。

本文為這個系列的第一篇,將討論一些預 備知識,它們是進行後續研究的基礎。

一些定義:

首先,我們來看一 些定義:

並發(Concurrency):兩個或更多的用戶嘗試同時更新數據庫 的同一條記錄。

並發沖突(Concurrency Confilct):兩個或更多的用 戶嘗試同時向同一條記錄的一個或多個字段提交沖突的值。

並發控制( Concurrency Control):解決並發沖突的技術。

樂觀並發控制 (Optimistic Concurrency Control):在提交當前事務之前,首先查看即將更 新的記錄是否被別的事務所改變的一種技術。

悲觀並發控制 (Pessimistic Concurrency Control):為紀錄加鎖以阻止其他事務訪問某些 記錄,以避免產生並發沖突的一種技術。

Linq to Sql的對象模型使用 樂觀並發控制的方式來發現和解決沖突問題。很顯然,它假設沖突發生的可能性 並不大。如果您需要使用悲觀並發控制來解決沖突問題,則可以使用其他方法( 例如自定義存儲過程供程序調用)。

調試方法:

Linq to Sql的相當 部分由編譯器來實現,而語言中的Linq語句最終會被轉化為Sql,因此如果要理 解Linq to Sql的工作,一定要將操作中所執行的Sql語句給挖掘出來。一般來說 ,要挖掘出操作中所使用的Sql語句,可以使用以下幾種方法(以下將使用Sql Server 2005自帶的AdventureWorks數據庫來作為示例):

1、獲取Query 所對應的SqlCommand對象:

在開發過程中,我們可以通過Query獲得對應的 Sql Command對象。請看如下代碼:

AdventureWorksDataContext db = new AdventureWorksDataContext();
var products = from p in db.Products
        where p.ProductID == 3
         select new { p.ProductID, p.Name };
foreach (var p in products)
{
  Console.WriteLine(p);
}
DbCommand cmd = db.GetCommand(products);
Console.WriteLine("--------- ---");
Console.WriteLine("Command Text: \n{0}", cmd.CommandText);
Console.WriteLine("------------");
Console.WriteLine("Command Type: \n{0}", cmd.CommandType);
Console.WriteLine("------------");
Console.WriteLine("Command Parameters:");
foreach (DbParameter p in cmd.Parameters)
{
  Console.WriteLine ("{0}: {1}", p.ParameterName, p.Value);
}
Console.ReadLine();

輸出結果如下:

Command Text:
SELECT [t0].[ProductID], [t0].[Name]
FROM [Production].[Product] AS [t0]
WHERE [t0].[ProductID] = @p0
------------
Command Type:
Text
------------
Command Parameters:
@p0: 3

可以看到,無論是Sql語句或是 參數都被打印了出來。事實上,由於我們得到了完整的SqlCommand對象,我們可 以獲取的信息並不止上述這些。

2、使用LINQ to SQL Debug Visualizer :

使用LINQ to SQL Debug Visiualizer,我們可以在調試程序時直觀地獲得 Query所對應的Sql語句以及參數,而不必獲得SqlCommand對象並打印信息。具體 使用方法詳見Scott Gu的這篇博文。

3、使用DataContext的Log功能:

DataContext自帶的Log屬性為一個TextWriter類型的對象,如果我們設置了 這個屬性,則DataContext所有的操作將會通過這個TextWriter對象輸出。與比 上述兩種方法相比,這個方法的優勢在於DataContext所執行的所有語句,無論 SELECT、INSERT、UPDATE或者是DELETE都會被輸出;而上面的兩種做法只能得到 Query的信息,也就是SQL語句的SELECT操作。

請看如下代碼,下面的代 碼將AdventureWorksDataContext對象的所有操作輸出至Console:

AdventureWorksDataContext db = new AdventureWorksDataContext();
db.Log = Console.Out;
Product  product = (from p in db.Products
          where p.ProductID == 1
          select p).First();
product.Name = "Hello World";
db.SubmitChanges();
Console.ReadLine();

輸出結果如下:

SELECT TOP (1) [t0].[ProductID], [t0].[Name], [t0].[ProductNumber], [t0]. [MakeFl
...
edDate], [t0].[rowguid], [t0].[ModifiedDate]
FROM [Production].[Product] AS [t0]
WHERE [t0].[ProductID] = @p0
-- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [1]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.21004.1
UPDATE [Production].[Product]
SET [Name] = @p11
WHERE ([ProductID] = @p0) AND ([Name] = @p1) AND ([ProductNumber] = @p2) AND (NO
...
NULL) AND ([rowguid] = @p9) AND ([ModifiedDate] = @p10)
-- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [1]
...
-- @p11: Input NVarChar (Size = 11; Prec = 0; Scale = 0) [Hello World]
-- Context: SqlProvider (Sql2005) Model: AttributedMetaModel Build: 3.5.21004.1

在這 裡我省略了大部分的輸出,不過從上面的片斷中我們已經可以看到SELECT和 UPDATE操作所使用的Sql語句以及參數都被打印了出來。這就是我們可以利用的 調試信息。

4、使用Sql Server Profiler:

其實使用Sql Server Profile來監聽數據庫操作應該是最容易想到的方法。相信各位朋友對於Sql Server Profiler的簡單操作也已經非常熟悉,我在這裡就不贅述了。

那 麼第3中做法相比,使用Sql Server Profiler有什麼又優點和缺點呢?使用Sql Server Profiler的優點可能就在於方便,我們不用寫代碼,也不用設法將Log信 息輸出至某個地方。缺點可能就在於Sql Server Profiler獲取到的信息會比較 多,而其中只有一小部分是我們需要的。而且,Sql Server Profiler的輸出也 不如DataContext的Log輸出來的工整、易讀。至於在開發過程中使用什麼做法比 較合適,我這裡也無法推薦,因為這需要您根據實際情況進行選擇了。

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