記一次代碼重構

来源:http://www.cnblogs.com/net515/archive/2016/09/30/5922608.html
-Advertisement-
Play Games

前段時間,我負責一款APP的介面開發,其中有一個新增的操作,邏輯比較複雜,涉及到9個數據表的數據改動,而且表又跨庫,這9個表呢,個別在別處還有單表操作,所以為了復用之前的數據層,筆者直接想到了使用分散式事務TransactionScope,在業務層直接調用多個DAO類的方法。 再說下這個新增操作吧, ...


      前段時間,我負責一款APP的介面開發,其中有一個新增的操作,邏輯比較複雜,涉及到9個數據表的數據改動,而且表又跨庫,這9個表呢,個別在別處還有單表操作,所以為了復用之前的數據層,筆者直接想到了使用分散式事務TransactionScope,在業務層直接調用多個DAO類的方法。

        再說下這個新增操作吧,這個APP是用來回收某產品的,所以這個新增操作是創建一個二手產品的訂單,首頁是五個項目,如圖(下圖中各具體項只是為說明數據結構),                   資料從左向右填寫,每次填完信息暫存在本地,點創建回收訂單,信息提交到後臺介面,其中【產品信息】下的配置信息和【產品描述】【圖片信息】的全部信息採用配置字典表分別存儲,產品描述關聯到訂單,而配置信息和圖片則關聯到產品。全部本地信息以JSON格式提交,格式如下
{
    "data": {
  "customer": {
           
            "CustomerName": "Ikki里",
            "Mobile": "13988888888",
 "Address": " "
        },
 "product": {
            "Name": "",
            "CPU": "",
            "Color": 0
        },
        "productCI": [
            "1,2",
            "2,1",
            "3,0"
 
        ],
        "productCheck": [
            "227,",
            "231,A+"
        ],
        "productPic": [
            {
                "ViewUrl": "http://imageup.xxxx.com/xxxxx/09/03/85b9213e-7bf3-4312-b59f-276ea0f9ac70_901.png",
                "ImgText": "左前",
                "PicPath": "/xxxx/09/03/85b9213e-7bf3-4312-b59f-276ea0f9ac70_{0}.png",
                "DictID": 349
            }
        ],
        "productPrice": {
            "PriceMax": "66.0",
            "PriceMin": "1.0",
            "Note": "abc",
        },
       
      
    }
}

 

       一切進行得還算順利,但當把程式部署到正式環境時,問題出現了,提示分散式事務未被初始化之類的錯誤,具體想不起來了,嘗試了網上的一些解決方法,比如本地DTC的一些設置,但都無效果,最後只好放棄了,又想到兩個解決方案,第一,在DAO層中重寫一個大的方法,包含全部的數據操作方法,在DAO類中DbTransaction 事務;第二,使用存儲過程,但想到要給存儲過程傳這麼多參數進去,我還是放棄了。好吧,就按第一種解決思路來。         重構的定義是在不改變系統的外部功能的前提下,只對內部的結構進行重新的整理,換到我現在的環境就是APP已經開發測試完成,所以我的介面的任何改變都不應該讓APP感覺到我的變化,接下來我做的事就是對現在的代碼重構,頓時覺得自己做一件很高大上的事,哈哈。        先說下之前的操作方法吧,代碼太多了,我就簡單示例下    
  private string Add(HttpContext context)
        {
            string result = string.Empty;
            using (System.Transactions.TransactionScope scope = new System.Transactions.TransactionScope())
            {
                #region 1、客戶資料
                CustomerDao.Add();
                     or  CustomerDao.Update  ();
                #endregion
                #region 2、產品信息,
                ProductDao.Add();
                     or  ProductDao.Update  ();
                #endregion                
                #region 4、圖片信息
                PicDao.Add();
                     or   PicDao.Update  ();
                #endregion
                #region  5、回收價格
                PriceDao.Add();
                     or PriceDao.Update  ();
                #endregion
                #region 3、產品描述信息
                ProductDesDao.Add();
                    or ProductDesDao.Update  ();
                #endregion
                scope.Complete();
                result = ERP.Common.Json.JsonHelper.ReturnJson(1, "保存成功!");
            }
            return result;
        }

        難道真的要把每個DAO下的方法複製粘貼出來,然後拼SQL,對參數?簡直難以想像,那樣還意味著以後要維護兩套DAO方法,並且是同一功能。關鍵是明天早上是必須要交付給客戶的,現在已經晚上快10點了...

        終於想到一個比較靠譜,又敏捷的方法,為了保險,我新建一個類,專門用來組織SQL和參數,把原來的DAO方法複製到這個類中,然後不執行SQL,而是用一個字典返回SQL+參數,這樣在上層調用接收到這個字典,用字典的原因是由於每個DAO方法的參數類型不同,這樣方便接收。把所有5個要執行的操作都接收完成後,再寫一個總的保存方法,這個方法里可以用IDbTransaction事務來保證安全。原來的單個表操作的方法也可以直接用這樣的方式來調用保存,不受影響,最重要的是APP端不用做任務的改動。       總的保存方法如下:
  1  public ResultModel SaveAll(Dictionary<string, object> dicParam)
  2         {
  3             ResultModel ret = new ResultModel();
  4             ret.Status = 0;
  5             ret.Message = "";
  6             lock (padlock)
  7             {
  8                 IDbTransaction trans = null;
  9                 try
 10                 {
 11                     using (var conn = new SqlConnection(DbConnString))
 12                     {
 13                         conn.Open();
 14                         trans = conn.BeginTransaction();
 15                         Dictionary<string, object> _param = new Dictionary<string, object>();
 16                         var sql = string.Empty;
 17                         var countSql = string.Empty;
 18                         var delSql = string.Empty;
 19                         //1、客戶資料
 20                         int sellerId = 0;
 21                         _param = (Dictionary<string, object>)dicParam["sellerCarInfo"];
 22                         SellerCarInfoModel sellerModel = (SellerCarInfoModel)_param["model"];
 23                         sql = _param["sql"].ToString();                       
 24                         if (sellerModel.ID > 0)
 25                         {
 26                             conn.Execute(sql.ToString(), sellerModel, trans);
 27                             sellerId = sellerModel.ID;
 28                         }
 29                         else {
 30                             countSql = _param["countSql"].ToString();
 31                             int cnt = conn.ExecuteScalar<int>(countSql, null, trans);
 32                             sellerModel.CustomerNo = string.Format("PC{0}{1}", DateTime.Now.ToString("yyMMdd"), (cnt + 1).ToString().PadLeft(4, '0'));
 33                             sellerId =conn.ExecuteScalar<int>(sql.ToString(), sellerModel, trans);
 34                         }
 35                         DebugLog("1、客戶資料", sql, sellerModel);
 36                         //2、車輛信息,不含車況
 37                         //1),基本信息,手續信息、圖片信息、配置信息
 38                         int carId = 0;
 39                         _param = (Dictionary<string, object>)dicParam["carBaseInfo"];
 40                         CarBaseInfoModel carBaseInfoModel = (CarBaseInfoModel)_param["model"];
 41                         sql = _param["sql"].ToString();
 42                         if (carBaseInfoModel.ID > 0)
 43                         {
 44                             conn.Execute(sql.ToString(), carBaseInfoModel, trans);
 45                             carId = carBaseInfoModel.ID;
 46                         }
 47                         else
 48                         {
 49                             carId = conn.ExecuteScalar<int>(sql.ToString(), carBaseInfoModel, trans);
 50                         }
 51                         DebugLog("2、車輛基本信息,手續信息", sql, carBaseInfoModel);
 52                         //2)配置信息
 53                         _param = (Dictionary<string, object>)dicParam["carCi"];
 54                         List<CarCIModel> listCi = (List<CarCIModel>)_param["list"];
 55                         sql = _param["insertSql"].ToString();
 56                         delSql= _param["delSql"].ToString();
 57                         if (listCi.Count > 0) {
 58                             conn.ExecuteScalar(string.Format(delSql, carId),null,trans);
 59                             foreach (var item in listCi)
 60                             {
 61                                 item.CarID = carId;
 62                                 conn.ExecuteScalar(sql, item, trans);
 63                             }
 64                         }
 65                         //3)圖片信息
 66                         _param = (Dictionary<string, object>)dicParam["carPic"];
 67                         List<AssessImageModel> listPic = (List<AssessImageModel>)_param["list"];
 68                         sql = _param["insertSql"].ToString();
 69                         delSql = _param["delSql"].ToString();
 70                         if (listPic.Count > 0)
 71                         {
 72                             conn.ExecuteScalar(string.Format(delSql, carId), null, trans);
 73                             foreach (var item in listPic)
 74                             {
 75                                 item.CarInfoID = carId;
 76                                 conn.ExecuteScalar(sql, item, trans);
 77                             }
 78                         }
 79                         //3、 [PingguCarInfo] 車冗餘表信息
 80                         int redundanceCarId = 0;
 81                         _param = (Dictionary<string, object>)dicParam["pingguCarInfo"];
 82                         PingguCarInfo pingguCarInfo = (PingguCarInfo)_param["model"];
 83                         sql = _param["sql"].ToString();
 84                         if (pingguCarInfo.Id > 0)
 85                         {
 86                             conn.Execute(sql.ToString(), pingguCarInfo, trans);
 87                             redundanceCarId = pingguCarInfo.Id;
 88                         }
 89                         else
 90                         {
 91                             redundanceCarId = conn.ExecuteScalar<int>(sql.ToString(), pingguCarInfo, trans);
 92                         }
 93                         DebugLog("3、 [PingguCarInfo] 車冗餘表信息", sql, pingguCarInfo);
 94                         //4、創建評估單
 95                         int pingguId = 0;
 96                         _param = (Dictionary<string, object>)dicParam["pingguOrder"];
 97                         PingguOrderModel pingguOrder = (PingguOrderModel)_param["model"];
 98                         pingguOrder.CarInfoId = carId;
 99                         pingguOrder.SellerId = sellerId;
100                         pingguOrder.RedundanceCarId = redundanceCarId;
101                         sql = _param["sql"].ToString();                  
102                             countSql = _param["countSql"].ToString();
103                             int _cnt = conn.ExecuteScalar<int>(countSql, null, trans);
104                             pingguOrder.PingguNo = string.Format("A{0}{1}", DateTime.Now.ToString("yyyyMMdd"), (_cnt + 1).ToString().PadLeft(4, '0'));
105                             pingguId =conn.ExecuteScalar<int>(sql.ToString(), pingguOrder, trans);
106                         DebugLog("4、創建評估單", sql, pingguOrder);
107                         //5、車況檢測信息
108                         _param = (Dictionary<string, object>)dicParam["carCheck"];
109                         List<CarCheckItemsModel> listCheck = (List<CarCheckItemsModel>)_param["list"];
110                         sql = _param["insertSql"].ToString();
111                         delSql = _param["delSql"].ToString();
112                         if (listCheck.Count > 0)
113                         {
114                             conn.ExecuteScalar(string.Format(delSql, pingguId), null, trans);
115                             foreach (var item in listCheck)
116                             {
117                                 item.CarId = pingguId;
118                                 conn.ExecuteScalar(sql, item, trans);
119                             }
120                         }
121                     
122                         //6、保存CarStoreAssociation關係                  
123                         _param = (Dictionary<string, object>)dicParam["carStoreAss"];
124                         Model.CarManage.CarStoreAssociation carStore = (Model.CarManage.CarStoreAssociation)_param["model"];
125                         sql = _param["sql"].ToString();
126                         carStore.CarID = carId;  
127                             conn.ExecuteScalar(sql.ToString(), carStore, trans);
128                         DebugLog("6、保存CarStoreAssociation關係", sql, carStore);
129                         ret.Status = 1;
130                         ret.Message = "";
131                        // throw new Exception();
132                         trans.Commit();
133                     }
134                 }
135                 catch (Exception ex)
136                 {
137                     ret.Status = 500;
138                     ret.Message = ex.Message;
139                     Log4NetHelper.Error("APP保存車輛信息時出錯:" + ex.Message, ex);
140                     trans.Rollback();
141                 }
142             }
143             return ret;
144         }
View Code

       現在想想,其實就是一個思路的問題,並沒有什麼難點,項目代碼就不貼了,如果真有需要,留下個郵箱好了


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

-Advertisement-
Play Games
更多相關文章
  • 創建測試的過程可參考如下鏈接 http://www.cnblogs.com/libaoquan/p/5296384.html (一)如何使用VS2015查看測試結果 問題描述:使用VS2010執行單元測試,會出現如下測試結果視窗 VS2015只有如下結果 查找相關資料後,發現VS2010會自動生成此 ...
  • 軟體是服務組織的系統,而任何組織一定會涉及到許可權;所以許可權控制是一個系統的核心基礎,不管你做啥系統都逃不過:有人的地方就有江湖,有系統就有許可權管理。 今天我們繼續講一下組織機構的管理: 線上演示視頻 優酷視頻地址,手機無法播放的點擊這裡:http://v.youku.com/v_show/id_XM ...
  • 安裝完成後,在“控制面板”中啟動“添加刪除程式”,選中Vs2008,點擊“更改、刪除”,輸入序列號:PYHYP-WXB3B-B2CCM-V9DX9-VDY8T ...
  • 本來沒打算單獨寫的,但是在自己弄測試小程式的時候,越寫發現不清楚的東西越多,所以實踐又一次證明:紙上得來終覺淺,絕知此事要躬行! 直接貼代碼了: 另外:祝大家國慶節快樂!我也要去參加一起長大的哥哥的婚禮了啊......時間啊,就是這麼匆匆溜走不回頭的....... ...
  • 引言 小弟工作過2家小作坊!項目經理使用的框架都是基於EF的Repository(倉儲)設計模式,我想說這種模式根本就是錯誤的使用! 更可怕的是博客園裡面也有很多這種教程! 之所以說錯誤的!是因為EF本身就是Repository(倉儲)的設計! 何必再套一層包裹給自己找事?而且也套的醜陋無比! 讓我 ...
  • VSCode,安裝插件:C# for Visual Studio Code (powered by OmniSharp),關於C#代碼的插件提示後,提示安裝DotNetCore.1.0.1 在安裝DotNetCore.1.0.1-VS2015Tools.Preview2.0.2出現0x80072f8... ...
  • 這個屬性我們平時可能並不怎麼用.先來看下MSDN上的解釋: 解釋的非常專業,然而我並沒有看懂. 說說我的理解吧:把這個屬性設置為false,看起來沒有變化,但操作上已經把他完全忽視了,不觸發事件,可以直接點到它下麵的東西. 這個屬性能方便的解決工作中常見的麻煩,比如下麵這個例子: 註意上面那部分.效 ...
  • 轉自:http://blog.csdn.net/samsone/article/details/7556781 1、格式化貨幣(跟系統的環境有關,中文系統預設格式化人民幣,英文系統格式化美元) string.Format("{0:C}",0.2) 結果為:¥0.20 (英文操作系統結果:$0.20) ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...