视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
[EntLib]微软企业库6DataAccessApplicationBlock扩展
2020-11-09 07:28:05 责编:小采
文档


虽然标题是对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());
 }

下载本文
显示全文
专题