你的位置:首页 > ASP.net教程

[ASP.net教程]记一次代码重构


      前段时间,我负责一款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

       现在想想,其实就是一个思路的问题,并没有什么难点,项目代码就不贴了,如果真有需要,留下个邮箱好了