关闭

.NET对存储过程的调用抽象封装

发表于:2012-6-28 09:52

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:王清培    来源:51Testing软件测试网采编

  最近一边参与公司的项目开发,一边还肩负着基础库的创建和维护。真真切切的体会到写框架的不容易,写出好的,方便使用的框架更不容易,需要考虑的东西太多,需要掌握的东西太多。不过不要紧我们正在前进的道路上。同志们一起加油!

  最近在使用存储过程的时候总觉得有点麻烦,尽管在前期对ORM和统一数据源接口封装已经下了很多功夫,对IDataParameter之类的接口已经进行了很好的封装,但是还是觉得麻烦。

  经过与DBA的沟通,他认为对存储过程的封装是有必要的,以他十几年的经验看,存储过程后期的移植是必不可少的。现在的项目是用SQLSERVER2008开发的,后期可能会移植到ORACLE上去,那么对存储过程的编写DBA考虑很周全。但是对于程序员来说,经验稍微丰富点的可能会通过某种工厂将具体对象脱耦,或者使用依赖倒置的原则来解决更换数据源问题。但是考虑到统一的使用方法,这里还是真的有必要进行封装的。那么如何封装?

  代码生成器的重要性

  这里为什么要牵扯到代码生成器呢?从我刚开始准备编写基础库的时候我就意识到代码生成器的重要性,当时的想法就是能为了完全的控制代码生成器。如果使用第三方的代码生成器可能在初期是可以满足要求,但是如果想把它做成成熟的开发平台是行不通的。借助代码生成器的功能,基础库的使用将变的更加流畅(后面将看到效果)。很明显的就是ORM和一些IDE中内置的代码生成,结合的很完美,让人痴迷。

  我们假设没有代码生成器,那些诸如通用的代码将需要我们程序员手动的敲,那个工作即枯燥也容易出错。所以需要代码生成器去帮我们生成我们想要的,符合某种规则的重复性的代码。比较典型的就是我们三层架构中必不可少的Model集合(有个概念要纠正一下,常常有程序员将Model对象集读成Model层,它并非层中的“层”,而是层中传递数据的结构)。

  有了自己公司的代码生成器之后,就可以按照公司的开发框架去不断的增强功能,使其逐渐变成开发平台,成熟了之后可能就是一套符合行业要求的快速开发框架。这也是个慢慢积累的过程,急不来。

  存储过程的使用分析

  我假设我们已经对IDataParameter对象进行了封装,我想对它简单的封装基本也都能满足日常要求了。一般都是根据当前项目链接数据库的类型字符串进行判断,然后生成相对应如:SqlParameter、OracleParameter、OleDbParameter等等,可能还包括一些开源的数据库扩展框架中的对象,这里的创建工厂可能是抽象工厂,当然方法很多种,实现效果就行。

  对其简单的封装我们在使用的时候需要使用工厂方法创建IDataParameter数组,如:

  1. Dictionary<stringobject> parameter = new Dictionary<stringobject>();  
  2. parameter.Add("PurchaseID", Purchase.TempSerialNo);//单据流水号  
  3. parameter.Add("WarehouseId", Purchase.InWarehouseID);//仓库ID 
  4. parameter.Add("UserID", Purchase.UserID);//操作ID 
  5. parameter.Add("UserName", Purchase.UserName);//操作人名称 
  6. parameter.Add("PurchaseDate", DBNull.Value);//采购日期 
  7. parameter.Add("BuyUserID", DBNull.Value);//采购人编号 
  8. parameter.Add("BuyUserName", DBNull.Value);//采购人名称 
  9. parameter.Add("BuyDate", DBNull.Value);//采购日期 
  10. parameter.Add("Memo", Purchase.Memo);//备注说明 
  11. IDataParameter[] parameterDic = IDataParameterFactory.CreateDbDataParameter(parameter);  
  12.  List<IDataParameter> listparameter = IDataParameterHelper.IDataParameterArrayToList(parameterDic);  
  13. listparameter.Add(WL.DAL.DAL_TB_WLPurchase.GetErrIDParametere());  
  14. using (Fast.Orm.IDataSourceOperation operation = Fast.Orm.IDataSourceOperationFactory.Create())  
  15. {  
  16. operation.ExecuteNonQuery(CommandType.StoredProcedure, "prc_WLPurchaseTmpAdd", listparameter.ToArray());  
  17. if (listparameter[listparameter.Count - 1].Value.ToString() == "0")  
  18. return true;  
  19. return false;  
  20. }

  一般性的封装基本都这样或者在IDataParameterFactory.CreateDbDataParameter(Entity)中加入根据实体的属性动态的创建IDataParameter[]对象,如果你的创建始终是使用反射的话那么将是不可取的。有兴趣的朋友可以参见本人的另一篇文章“利用抽象、多态实现无反射的绿色环保ORM框架”对实体的使用如果不能摆脱反射,那么在以后的基础库扩展中将面临着很多性能问题,这里需三思。

  由于很少存储过程的参数名称都是对应的实体的属性名称,这种对应关系很难做到,或者说是做到的话需要DBA花点时间呢,在命名上也是个约束。

  如果存储过程有N个参数的话我们需要对照数据库设计文档来编写IDictionary项,在一般的项目中都将复杂的业务逻辑封装在存储过程中实现,所以存储过程的数量也是不少的。这样一来也算是一个比较浪费时间的工作。

  那么如果减少编码量,让存储过程的调用变的简单,而且对用户来说是透明的?

  抽象存储过程的参数使其变成参数实体抽象

  由于在设计绿色ORM的过程中总结了很多好的想法,也确实能感觉到对简单实体的抽象能使后期的扩展变的更加自如。比如,不需要那么费力的使用反射获取属性元数据,直接使用字典集合就能得到属性的名称和值。那么我也使用类似的设计思路来设计了参数实体对象。

41/41234>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号