您的当前位置:首页正文

[EntLib]微软企业库6DataAccessApplicationBlock扩展

2020-11-09 来源:品趣旅游知识分享网

虽然标题是对6的扩展,其实对于4、5同样适用,因为企业库在这几个版本中没太大变化 该扩展主要针对DataAccessorT,该类在创建时要传递几种接口:IParameterMapper,IRowMapperT,IResultSetMapperT,其中IRowMapperT企业库提供了MapBuilderT静态类来辅助创建

虽然标题是对6的扩展,其实对于4、5同样适用,因为企业库在这几个版本中没太大变化

该扩展主要针对DataAccessor,该类在创建时要传递几种接口:IParameterMapper,IRowMapper,IResultSetMapper,其中IRowMapper企业库提供了MapBuilder静态类来辅助创建相应的对应关系,但对于IParameterMapper和IResultSetMapper没提供现成的类(也许有,但我没找到,毕竟没去研究它的源码)

以下是具体相关的代码,设计思路是:IParameterMapper和IResultSetMapper其实都是要实现一个约定的方法,而对于该方法,我直接设置通用类,该类接受具体的实现委托,该委托由coder决定,而无需coder反复去创建相关类,减少代码量

PS:DbCommand.Parameters.AddRange接受DbParameter参数,所以可以直接传递具体的DbParameter

1、GeneralParameterMapper

 /// 
 /// 通用IParameterMapper
 /// 如果在Execute前要传递的DbParameter已被其它DbCommand使用,将产生异常
 /// 所以应该要调用DbCommand.Parameters.Clear方法释放其它DbCommand对DbParameter的占用
 /// 
 public class GeneralParameterMapper : IParameterMapper
 {
 private Action _act;
 /// 
 /// GeneralParameterMapper
 /// 
 /// 
 /// 定义如何将parameterValues赋给DbCommand的委托
 /// 如果不传,将使用默认委托,该委托不校验要传递的parameterValues在DbCommand是否已定义
 /// 此时反复执行Execute将会导致异常,以保证不会因为编码问题导致反复查询
 public GeneralParameterMapper(Action act = null)
 {
 if (act != null)
 {
 this._act = act;
 }
 else
 {
 this._act = (cmd, paramters) =>
 {
 cmd.Parameters.AddRange(paramters);
 };
 }
 }
 #region IParameterMapper 成员
 /// 
 /// IParameterMapper.AssignParameters
 /// 
 /// 
 /// 
 public void AssignParameters(DbCommand command, object[] parameterValues)
 {
 if (parameterValues != null && parameterValues.Length > 0)
 {
 this._act(command, parameterValues);
 }
 }

 #endregion
 }
2、GeneralResultSetMapper
 /// 
 /// 通用IResultSetMapper
 /// 
 /// 
 public class GeneralResultSetMapper : IResultSetMapper
 {
 private Func _func;
 /// 
 /// GeneralResultSetMapper
 /// 
 /// 根据IDataReader如何返回T委托
 public GeneralResultSetMapper(Func func)
 {
 if (func == null)
 {
 throw new ArgumentNullException();
 }
 this._func = func;
 }
 #region IResultSetMapper 成员
 /// 
 /// IResultSetMapper.MapSet
 /// 
 /// IDataReader
 /// List集合,如果Count为0,表示无数据,不会返回null值
 public IEnumerable MapSet(IDataReader reader)
 {
 List list = new List();
 while (reader.Read())
 {
 list.Add(this._func(reader));
 }
 return list;
 }

 #endregion
 }

在这两个类的基础上,又封装了个扩展类,专门用于微软企业库DataAccessor的扩展,同时包含了其它的Execute扩展,以下是具体代码,因个人喜好问题,没封装对应Proc的扩展方法,其实代码都一样
PS:此处扩展因为DbCommand是可以在委托中访问到的,所以对于CommandTimeOut之类的就不做参数传递

 /// 
 /// 微软企业库数据相关的帮助类
 /// 
 public static class EntLibDbHelper
 {
 /// 
 /// 批量查询Sql并自动填充实体,如果不需要传递DbParameter,建议不要使用该方法,应使用Database.ExecuteSqlStringAccessor方法
 /// 
 /// 
 /// 
 /// 
 /// 指定委托确认对要传递的Sql参数如何处理,该值可以传递null,为null时使用默认委托,该委托直接将parameterValues传递给cmd.Parameters.AddRange方法
 /// 指示EntLib如何填充T,如果不传,将默认按T的属性进行对应赋值
 /// 要传递的Sql参数,此部分对应parameterMapperAction
 /// 
 public static IList ExecuteBySqlString(this Database db, string sql, Action parameterMapperAction, IRowMapper rowMapper = null, params object[] parameterValues)
 where T : new()
 {
 if (rowMapper == null)
 {
 rowMapper = MapBuilder.BuildAllProperties();
 }
 IParameterMapper parameterMapper = new GeneralParameterMapper(parameterMapperAction);
 return db.CreateSqlStringAccessor(sql, parameterMapper, rowMapper).Execute(parameterValues).ToList();
 }
 /// 
 /// 批量查询Sql并自动填充实体,如果不需要传递DbParameter,建议不要使用该方法,应使用Database.ExecuteSqlStringAccessor方法
 /// 
 /// 
 /// 
 /// 
 /// 指定委托确认对要传递的Sql参数如何处理,该值可以传递null,为null时使用默认委托,该委托直接将parameterValues传递给cmd.Parameters.AddRange方法
 /// 指示EntLib如何填充T
 /// 要传递的Sql参数,此部分对应parameterMapperAction
 /// 
 public static IList ExecuteBySqlString(this Database db, string sql, Action parameterMapperAction, Func resultSetMapperFunc, params object[] parameterValues)
 {
 IParameterMapper parameterMapper = new GeneralParameterMapper(parameterMapperAction);
 IResultSetMapper resultSetMapper = new GeneralResultSetMapper(resultSetMapperFunc);
 return db.CreateSqlStringAccessor(sql, parameterMapper, resultSetMapper).Execute(parameterValues).ToList();
 }
 /// 
 /// 执行SQL文本,并返回受影响行数
 /// 
 /// 
 /// 
 /// 
 /// 
 public static int ExecuteNonQueryBySqlString(this Database db, string sql, Action parameterSetAction = null)
 {
 return db.ExecuteBySqlString(sql, (cmd) => { return db.ExecuteNonQuery(cmd); }, parameterSetAction);
 }
 /// 
 /// 执行SQL文本,返回DataReader
 /// 
 /// 
 /// 
 /// 
 /// 
 public static IDataReader ExecuteReaderBySqlString(this Database db, string sql, Action parameterSetAction = null)
 {
 return db.ExecuteBySqlString(sql, (cmd) => { return db.ExecuteReader(cmd); }, parameterSetAction);
 }
 /// 
 /// 执行SQL文本,返回第一行第一列数据
 /// 
 /// 
 /// 
 /// 
 /// 
 public static object ExecuteScalarBySqlString(this Database db, string sql, Action parameterSetAction = null)
 {
 return db.ExecuteBySqlString(sql, (cmd) => { return db.ExecuteScalar(cmd); }, parameterSetAction);
 }
 private static T ExecuteBySqlString(this Database db, string sql, Func resultFunc, Action parameterSetAction = null)
 {
 var cmd = db.GetSqlStringCommand(sql);
 if (parameterSetAction != null)
 {
 parameterSetAction(cmd);
 }
 return resultFunc(cmd);
 }
 }
顺带补充个通用的Data扩展
 /// 
 /// 数据相关的帮助类
 /// 
 public static class DbHelper
 {
 /// 
 /// 从DataReader中读取可空对象
 /// 
 /// 泛型T
 /// IDataReader
 /// Key
 /// 
 public static Nullable GetNullable(this IDataRecord dr, string key)
 where T : struct
 {
 return dr[key] == null || dr[key] == DBNull.Value ? (Nullable)null : (T)dr[key];
 }
 /// 
 /// 当DataReader读取对象为空时,返回defaultValue
 /// 
 /// 泛型T
 /// IDataReader
 /// Key
 /// 当取到的数据为DBNull时,应当返回的默认值
 /// 
 public static T GetDefaultWhileNullable(this IDataRecord dr, string key, T defaultValue = default(T))
 {
 return dr[key] == null || dr[key] == DBNull.Value ? defaultValue : (T)dr[key];
 }
 /// 
 /// 从DataReader中读取字符串并除前后空白字符后
 /// 
 /// IDataReader
 /// Key
 /// 
 public static string GetTrimedString(this IDataRecord dr, string key)
 {
 return dr[key].ToString().Trim();
 }
 }

具体使用代码如下:
string sql = @"SELECT [pdate]
 ,[pbegtime]
 ,[pendtime]
 ,[pid]
 ,[pdateid] FROM tbltime WITH(NOLOCK)
WHERE pid=@PID";

 IRowMapper rowMapper = MapBuilder.MapNoProperties()
 .Map(p => p.ID).ToColumn("pdateid")
 .Map(p => p.Name).WithFunc((dr) =>
 {
 return string.Format("{0}-{1}", dr.GetTrimedString("pbegtime"), dr.GetTrimedString("pendtime"));
 })
 .Build();
 var list = db.ExecuteBySqlString(sql, null, rowMapper, new SqlParameter("@PID", 12345) { DbType = DbType.Int32 });

 MessageBox.Show(list.Count.ToString());


 IParameterMapper paramterMapper = new GeneralParameterMapper();
 var _productAccessor = db.CreateSqlStringAccessor(sql, paramterMapper, rowMapper);

 var products = _productAccessor.Execute(new SqlParameter("@PID", 12345) { DbType = DbType.Int32 }).ToList();
 if (products != null && products.Count > 0)
 {
 MessageBox.Show(products.Count.ToString());
 }
显示全文