.Net高級進階,在複雜的業務邏輯下,如何以最簡練的代碼,最直觀的編寫事務代碼?

来源:http://www.cnblogs.com/1996V/archive/2017/11/08/7798111.html
-Advertisement-
Play Games

本文將通過場景例子演示,來通俗易懂的講解在複雜的業務邏輯下,如何以最簡練的代碼,最直觀的編寫事務代碼。 通過一系列優化最終達到兩個效果,1.通過代碼塊來控制事務(分散式事務),2.通過委托優化TransactionScope的編碼寫法。 本文需要的知識點:1. Action委托 2. 分散式事務Tr ...


本文將通過場景例子演示,來通俗易懂的講解在複雜的業務邏輯下,如何以最簡練的代碼,最直觀的編寫事務代碼。

通過一系列優化最終達到兩個效果,1.通過代碼塊來控制事務(分散式事務),2.通過委托優化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 。

那麼,有沒有一種寫法,能讓我們 更簡單更方便  不用每次複製粘貼代碼形式 來實現 事務的編寫?

有!

TransactionScope:

  在早期.net時代,如果想使用事務,就用SqlTransaction來實現,而每個SqlTransaction都會用同一個SqlConnection連接對象。
  如果邏輯簡單還好說,如果邏輯稍微複雜的話,想用多個Dal方法來共同組合一個事務的話,就非常費腦筋的,就像上文這樣演變的 第一版 和 第二版。
  為此,在.Net2.0時代,TransactionScope誕生了,微軟官方描述:代碼塊事務,還有一個別稱:分散式事務。
  它實現了IDisposable介面,可以把它被實例化開始到被Dispose掉之間的代碼作為一個事務,也就是它的存在,最終讓你的代碼塊所嵌套在其中多個DAL方法變成“一個方法”

 

那麼,當我們使用它以後,我們就可以這樣編寫:

 

【示例三】

 現在,大家對 TransactionScope 有了基本的印象,那麼現在考慮到代碼的可讀性和靈活性,我將要對當前風格再次改寫,通過委托的形式讓代碼結構層次更加分明。

 1         /// <summary>
 2         /// 事務語句統一執行
 3         /// </summary>
 4         /// <param name="ac">委托</param>
 5         /// <returns></returns>
 6         public static bool TransactionExecute(Action ac)
 7         {
 8             try
 9             {
10                 using (TransactionScope ts = new TransactionScope())
11                 {
12                     ac.Invoke();
13                     ts.Complete();
14                 }
15                 return true;
16             }
17             catch
18             {
19                 return false;
20             }
21         }    

然後,我們的介面方法的編碼變成了這樣:

 1         /// <summary>
 2         /// 商品倉庫的入庫作業操作
 3         /// </summary>
 4         /// <param name="iData">入庫數據集合</param>
 5         /// <returns></returns>
 6         public string WarehouseGoodsOperate(List<InboundModel> iData)
 7         {
 8             Action ac = () => { };//聲明一個委托
 9             foreach (InboundModel item in iData)
10             {
11                 if (item.type == "商品")
12                 {
13                     ac += () =>
14                     {
15                         IServices.Insert(item);
16                         IServices.UpdateGoods(item);
17                     };
18                 }
19                 if (item.type == "原材料")
20                 {
21                     ac += () =>
22                     {
23                         IServices.Insert(item);
24                         IServices.UpdateInventory(item);
25                     };
26                 }
27             }
28             if (IServices.TransactionExecute(ac))
29             {
30                 return "成功";
31             }
32             return "失敗";
33         } 

 通過上面這樣的寫法,最終讓代碼風格更乾凈,同時在 事務的 處理上更靈活方便, 我們只需要把想要執行的 方法 讓 ac 給包進去, 最後在調用 TransactionExecute 統一執行。

 基於自己的場景可以定製自己的TransactionExecute,本文著重指出利用委托來優化該情況下的編碼思想,至於TransactionExecute,這裡只是做個簡單的科普,其中有更多可挖掘的地方,感興趣的童鞋可以自行百度。

 當然,採用這種委托寫法,需要註意一點:

 

因為 類 是 引用類型 ,傳遞的地址和值類型不同, 所以最終你的委托執行的是  你最後對實例的更改, 所以你認為的能行,實際上是不能行。

那麼,怎樣解決這樣情況?
逐個逐個的賦值,或者用反射?
不用,我們可以通過繼承 ICloneable 介面,然後通過淺複製的方式實現Clone方法。

    class SysUser : ICloneable
    {
        public object Clone()
        {
            return this.MemberwiseClone(); 
        }
    }

最後,我們就可以這樣:

 

讓正確的程式更快比讓快速的程式正確要容易的多

 

我喜歡和我一樣的人交朋友,不被環境影響,自己是自己的老師,歡迎加群 .Net web交流群, QQ群:166843154 欲望與掙扎

 

作者:小曾
出處:http://www.cnblogs.com/1996V/p/7798111.html  歡迎轉載,但任何轉載必須保留完整文章,在顯要地方顯示署名以及原文鏈接。如您有任何疑問或者授權方面的協商,請給我留言
.Net交流群, QQ群:166843154 欲望與掙扎 

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ...
  • 環境說明 服務端配置 第一個裡程碑:在m01上部署LNP架構 cd /server/scripts sh nginx_install.sh sh php_install.sh nginx_install.sh 腳本內容 #!/bin/bash # base setting mkdir -p /ser ...
  • 學習Linux決心計劃書 我叫耿長學,來自河南省鄧州市,經過老男孩教育運維班5個月學習後,我一定要達到的薪水目標是11000元,為了達到此目標我將採取如下10大行動或方案: 1、每天早上5:30-6:00起床,不睡懶覺,早起學習,早上起來講自己學習過的內容,多講,不停的講,練習自己的口才; 2、每天 ...
  • 博客園 首頁 新隨筆 聯繫 管理 隨筆 - 149 文章 - 28 評論 - 205 nginx簡易教程 目錄 nginx簡易教程 概述 安裝與使用 安裝 從源代碼編譯 Nginx Windows 安裝 使用 nginx 配置實戰 http反向代理配置 負載均衡配置 網站有多個webapp的配置 h ...
  • Varnish的VCL子程式 以下內容參考: http://book.varnish software.com/4.0/ VCL子進程,在其中定製Varnish的行為。VCL子常式可用於:添加自定義標頭,更改Varnish錯誤消息的外觀,在Varnish中添加HTTP重定向功能,清除內容以及定義緩存 ...
  • Nginx的靜態處理能力很強,但是動態處理能力不足,因此,在企業中常用動靜分離技術。動靜分離技術其實是採用代理的方式,在server{}段中加入帶正則匹配的location來指定匹配項針對PHP的動靜分離:靜態頁面交給Nginx處理,動態頁面交給PHP FPM模塊或Apache處理。在Nginx的配 ...
  • vim 插入模式 a 游標後 A 行尾 o 游標所在行下一行 O 游標所在行上一行 i 游標前 I 行首 s 刪除游標所在位置的字元併進入插入模式 命令模式 d 刪除 dd 刪除當前行 dgg 刪除游標到文檔首 dG 刪除游標到文檔尾部 d$ 刪除游標到行尾,包括游標所在位置字元 d^ 刪除游標到行 ...
  • 1.使用xshell連接虛擬機,也可直接在虛擬機中敲命令。 以下是xshell上的命令: 首先安裝HTTPD包 [root@one ~]# mount /dev/sr0 /mnt[root@one ~]# yum install httpd重啟服務查看靜態 [root@one ~]# systemc ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...