本文将通過場景例子示範,來通俗易懂的講解在複雜的業務邏輯下,如何以最簡練的代碼,最直覺的編寫事務代碼。
用一句話貫穿全文就是:通過委托來讓TransactionScope的編碼實作更直覺,并不是講述TransactionScope的其它如分布式、ACID等場景應用及解決方案。
通過一系列優化最終達到兩個效果,1.讓不了解TransactionScope的童鞋通過代碼塊TransactionScope來控制事務,2.讓了解TransactionScope的童鞋簡單概述本執行個體的委托思想抛磚引玉來優化TransactionScope的編碼寫法。
本文需要的知識點:1. Action委托 2. 分布式事務TransactionScope(不懂不要緊,文中會通過示例一和示例二簡單講解這是啥,為啥要用)
----------------------
.Net Web開發技術棧
.Net進階進階,教你如何建構企業模型資料攔截層,動态控制字段驗證
.Net進階進階,在複雜的業務邏輯下,如何以最簡練的代碼,最直覺的編寫事務代碼?
web安全:通俗易懂,以執行個體講述破解網站的原理及如何進行防護!如何讓網站變得更安全。
web安全:QQ号快速登入漏洞及被盜原理
.Net,Dll掃盲篇,如何在VS中調試已經編譯好的dll?
示例一和示例二,主要是來講解 TransactionScope 是什麼,為什麼要用TransactionScope。
示例三(重要)則是優化寫法,增加代碼的靈活性和可讀性。
現在,你要寫個入庫接口,大緻意思就是: 勾選一條商品,然後寫上數量,點選入庫按鈕,将會産生一條入庫記錄,同時 這個商品的所對應的 庫存數量 也會 更新。
因為涉及到庫存,是以要用事務來保證資料安全。
StorageTask:入庫作業表,存寫入庫記錄
GoodsInventory:商品庫存表, 裡面放的是 不同商品的 詳細介紹、數量等資訊
那麼我們的實作 , 可能是 這樣的 , 如圖:

上圖的代碼,我們主要是先看 商品入庫操作 GoodsInventoryOperate 這個Dal方法,放圖:
上面的這是一個Dal方法,事務寫法很大衆,很正常,代碼沒毛病。
好,現在,我們的業務要求要改一下,改成這樣的:
勾選了一條商品,輸入該條商品的入庫數量,然後又勾選了一條原材料,輸入該原材料的入庫數量,最終點選入庫按鈕,要 産生 商品的入庫記錄和原材料的入庫記錄, 還要 分别修改 所對應的 商品庫存表和原材料庫存表 的 庫存數量
那麼,我們就要修改下這個接口,首先,參數由原來的 單行的參數 改為 集合形式的 參數,
那麼我們的接口代碼也随之修改,如下圖:
然後我們在看看 這個入庫操作方法 InventoryOperate
我們來對比下,我們把之前的 商品入庫操作 GoodsInventoryOperate 方法 給改成了 入庫操作方法 InventoryOperate 。
實際上,入庫操作方法 InventoryOperate = 商品入庫操作 + 原材料入庫操作 ,但是因為 業務的更改,讓我們不得不把 原本 Dal層中的兩個方法代碼 給 複制粘貼到一起,形成第三個方法,也就是入庫操作方法 InventoryOperate 。
那麼,有沒有一種寫法,能讓我們 更簡單更友善 不用每次複制粘貼代碼形式 來實作 事務的編寫?
有!
在早期.net時代,如果想使用事務,就用SqlTransaction來實作,而每個SqlTransaction都會用同一個SqlConnection連接配接對象。
如果邏輯簡單還好說,如果邏輯稍微複雜的話,想用多個Dal方法來共同組合一個事務的話,就非常費腦筋的,就像上文這樣演變的 第一版 和 第二版。
為此,在.Net2.0時代,TransactionScope誕生了,微軟官方描述:代碼塊事務,還有一個别稱:分布式事務。
它實作了IDisposable接口,可以把它被執行個體化開始到被Dispose掉之間的代碼作為一個事務,也就是它的存在,最終讓你的代碼塊所嵌套在其中多個DAL方法變成“一個方法”
那麼,當我們使用它以後,我們就可以這樣編寫:
現在,大家對 TransactionScope 有了基本的印象,那麼現在考慮到代碼的可讀性和靈活性,我将要對目前風格再次改寫,通過委托的形式讓代碼結構層次更加分明。
然後,我們的接口方法的編碼變成了這樣:
通過上面這樣的寫法,最終讓代碼風格更幹淨,同時在 事務的 處理上更靈活友善, 我們隻需要把想要執行的 方法 讓 ac 給包進去, 最後在調用 TransactionExecute 統一執行。
基于自己的場景可以定制自己的TransactionExecute,本文着重指出利用委托來優化該情況下的編碼思想,至于TransactionExecute,這裡隻是做個簡單的科普,其中有更多可挖掘的地方,感興趣的童鞋可以自行百度。
當然,采用這種委托寫法,需要注意一點:
因為傳遞的是引用,并且用用到了lambda,導緻了閉包,最終在Invoke時在匿名類中會用同一引用。
那麼,怎樣解決這樣情況?
逐個逐個的指派,或者用反射?
不用,我們可以通過繼承 ICloneable 接口,然後通過淺複制的方式實作Clone方法(淺複制拷貝時,string會建立新的執行個體,如果尚有除string之外的引用類型還需深拷貝)。
最後,我們就可以這樣:
讓正确的程式更快比讓快速的程式正确要容易的多
我喜歡和我一樣的人交朋友,不被環境影響,自己是自己的老師,歡迎加群 .Net web交流群, QQ群:166843154 欲望與掙紮