2005.4.8 付仲愷
基礎預習
熟悉Microsoft ADO.NET
瞭解Web Services基礎開發
瞭解.NET檔案集操作
議題
並發問題
串連池
事務
可抽取的資料訪問層
並發性問題
在可中斷連線架構中必須要面對並發問題
當兩個(或多個)使用者擷取並修改相同的記錄,然後試圖同時維持各自的修改時,將會發生衝突:髒讀u,不可重複讀取,虛幻讀
當提交多個更新的時候,會造成部分更新無法正確完成
悲觀與樂觀(ADO.NET構建)並發鎖
悲觀鎖:無論讀寫都加鎖
樂觀鎖:只有寫加鎖,讀不加鎖(ADO.NET)
ADO.NET中對並發性問題的處理
與DataAdapter對象相串連的DataSet對象使用樂觀鎖來處理記錄內容衝突
DataAdapter設定精靈能夠修改Update和Delete語句以檢測是否發生了並發問題
當ContinueUpdateOnError為false(預設值)時,在發生第一個衝突的時候會拋出DBConcurrencyException異常
無論是true還是false,對於有並發性問題的資料行都會取消更新操作,它們之間的不同是為true時還會更新其它行,為false時會馬上拋出異常。
捕獲該異常並且通知使用者,或者處理該異常或提示使用者下一步需要做出哪些選擇
示範一
處理並發性問題
先同時開啟兩個表單,都Load出一樣的資料,然後修改左邊的1,2行資料儲存後,修改右邊的1,2行資料,這時就會拋出並發性錯誤的異常,並且顯示0行被改變,也就是沒有完成更新。
它只對於第一個並發的問題彈出對話方塊,而對於第二個並發問題並沒有提示錯誤,因為它一旦拋出異常,就不會對後面的資料進行操作了。
另一種示範是把ContinueUpdateOnError的屬性設定為True,然後進行更新。GetErrors()方法能擷取出產生衝突的資料行。
左邊更新了3行資料,右邊更新了3行資料,其中有兩行資料有並發衝突。
結果並沒有拋出異常的對話方塊,並且沒有發生並發性衝突的更新會更新成功。
串連池
串連池可以極大地提升效能和可擴充性
避免由建立串連所帶來的大量消耗
通過在連接字串中添加以下屬性來調節串連池
Pooling=true;Max Pool Size=5;Min Pool Size=3;
上面的字串將開啟串連池,並且確保在串連池中至少存在著3個串連,並且最多為5個串連
當達到最大串連時,開啟新串連的請求將排隊一段可配置的時間
預設等待時間15秒,如果超過15秒還未獲得串連,就會拋出逾時異常。
當使用OleDbConnection時,如果要關閉串連池在連接字串中添加"OLE DB Services=-4"
注意
串連是通過對連接字串精確匹配的法則被池化的。池化機制對名稱-值對間的空格敏感
例如,下面的兩個連接字串將產生單獨的池,因為第二個字串包含了一個額外的Null 字元。
"Integrated Security=SSPI;Database=Northwind"
"Integrated Security=SSPI ;Database=Northwind"
Close方法將串連放回串連池
Dispose方法則直接銷毀串連,而不放回到串連池中
示範二
串連池
簡單串連池,最後沒有Close是為了示範查看串連池中的串連。開啟SQL Server管理器,能看見串連池中的三個等待啟用的連結。
進階串連池,建立多線程調用Go方法,啟動線程並讓線程等待。
排隊超過15秒,拋出逾時異常
我們可以通過修改連接字串調大逾時時間或者調大最大串連數
50個線程不停地擷取SQL版本號碼,其中每個線程執行100次,所有線程都執行完之後,共會擷取5000次SQL的版本號碼資訊。
使用串連時我們不到萬不得已不要開啟串連,開啟串連後也應該及時關閉它。
事務
ACID原則:原子性,一致性,隔離性,持久性
事務行為要麼完成所有動作,要麼不做任何動作
同時提交或者復原所有的修改
不是所有的SQL語句都允許出現在事務中
例如建立資料庫的操作、修改表的操作,是不允許出現在事務中的
ADO.NET事務只能應用於單一串連中
SqlTransaction對象從SqlConnection.BeginTransaction()方法中返回
SqlTransaction類
SqlTransaction trans=conn.BeginTransaction();
執行個體化事務對象
隔離等級枚舉(IsolationLevel):Chaos,ReadCommitted,ReadUncommitted,RepeatableRead,Serializable,Unspecified
Serializable是最進階別的隔離
隔離等級越高,越能更好處理並發性問題。ADO.NET預設使用ReadCommitted層級的隔離。
處理工作:Insert,Update,Delete
要麼提交所有的修改:trans.Commit();
要麼如果發生錯誤,撤回所有的修改:trans.RollBack();
隔離等級
Serializable提供了最高的隔離等級,但卻只有最低的執行效率
Serializable是序列化的方式,也就是以串列的處理方式一個挨一個進行訪問,所以效率最低。
示範三
本地事務操作
進階事務
為了執行跨資料庫事務,需要通過System.EnterpriseServices向分散式交易協調器(DTC)註冊連結
分散式交易也能進行本地化操作,但是它會相對有較大的開銷,因為本地交易處理不需要與分布式協調器進行互動。
在中介層Web服務上添加:System.EnterpriseServices.Transaction屬性
TransactionOption枚舉:Disable,NotSupported,Required,RequiresNew,Supported
TransactionIsolationLevel枚舉:Chaos,ReadCommitted,ReadUnCommitted,RepeatableRead,Serializable
Serializable是最進階別的隔離
連接字串中的Enlist項表明串連是否參與到事務操作中
為true表示參與事務操作
當連接字串中Enlist=false時,可以調用SqlConnection.EnlistDistributedTransaction方法以執行事務操作
對分散式交易的控制方法
使用AutoComplete屬性對方法進行注釋。如果方法正常執行完畢,則自動認可事務,而如果發生異常則自動執行復原操作
調用ContextUtil類的靜態方法SetComplete或SetAbort來實現事務提交和復原操作
示範四
跨資料庫事務
要使用COM+事務需要添加EnterpriseServices引用。
方法上加了標籤,表示需要執行事務的操作。方法的最後會拋出一個異常,讓事務自動復原。只有中間的Enlist為false且沒有調用EnlistDistributedTransaction方法的操作不會復原,其它都會隨交易回復。
使用事務的注意事項
在一組操作中,只有在需要保證ACID特性時才使用事務
降低事務的粒度,以最小化鑑效組資料庫鎖的時間
不要為單個SQL語句使用交易處理。SQL Server自動把每個語句作為單個交易處理執行
層次化應用程式架構
多層應用程式將代碼分為不同的邏輯代碼層
非常普遍的設計方案是3層架構設計:展示層,商務邏輯層和資料訪問層
合理的層次化設計帶來了很多益處:代碼複用,可擴充性,封裝性,鬆散的耦合性,高彙總性
我們能夠設計一個可抽取的資料訪問層來完全抽象資料存放區
層次化應用程式架構——概念
3層是在邏輯上劃分的,在物理上不一定要按這種嚴格的劃分。
資料訪問層——概念
位於應用程式的商務邏輯與資料存放區之間的代碼層
包含了應用程式所有的資料存取碼;提供CRUD操作函數
商務邏輯層只與資料訪問層有鬆散的耦合關係
可抽取資料訪問層
可抽取資料訪問層為應用程式提供良好的可擴充性
設計可抽取資料訪問層可以很容易地修改,更新,資料存放區而不需要重新編譯其它層
通過介面實現松耦合度
通過基於介面的原廠模式以實現可抽取組件
將資料訪問層從商務邏輯層中完全抽象出來
基於介面的編程——概念
介面類似於合約
基於介面的編程消除了從實際代碼中實現的方法的耦合性
提供了多態機制
實現“可抽取”組件
可抽取組件——概念
.NET允許通過Assembly.Load()以及Assembly.CreateInstance()來動態負載檔案集和類
通過配置指向具體的資料訪問層類
“新的”或者“改進的”(不同)組件可以“插入”到現存的應用程式中
不需要從新編譯那些依賴介面的代碼
非常低的耦合意味著極大的可擴充性
示範五
可抽取資料訪問層
GetDaL是資料訪問層,它根據傳入參數,動態負載檔案集建立對應執行個體
這三個介面的實現其實都是組件。我們把三種不同顏色訪問的方法抽象成了IDaL的介面,商務邏輯層並不需要關心是訪問哪一個對象或者組件,它只需調用GetDaL即可擷取對應顏色。
總結
並發問題是在可取消連結資料模型中必須要處理的問題
串連池能夠改進效能和擴充性
事務確保資料的更新的原子性,持久性,隔離性和持久性
可抽取資料訪問層是通過松耦合實現可擴充性的強有力的方法
2010.10.22