[EntLib]微软企业库6 Data Access Application Block 扩展

来源:互联网 发布:wish数据 编辑:程序博客网 时间:2024/06/09 01:09

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

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

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

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

1、GeneralParameterMapper

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

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

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

    /// <summary>    /// 微软企业库数据相关的帮助类    /// </summary>    public static class EntLibDbHelper    {        /// <summary>        /// 批量查询Sql并自动填充实体,如果不需要传递DbParameter,建议不要使用该方法,应使用Database.ExecuteSqlStringAccessor方法        /// </summary>        /// <typeparam name="T"></typeparam>        /// <param name="db"></param>        /// <param name="sql"></param>        /// <param name="parameterMapperAction">指定委托确认对要传递的Sql参数如何处理,该值可以传递null,为null时使用默认委托,该委托直接将parameterValues传递给cmd.Parameters.AddRange方法</param>        /// <param name="rowMapper">指示EntLib如何填充T,如果不传,将默认按T的属性进行对应赋值</param>        /// <param name="parameterValues">要传递的Sql参数,此部分对应parameterMapperAction</param>        /// <returns></returns>        public static IList<T> ExecuteBySqlString<T>(this Database db, string sql, Action<DbCommand, object[]> parameterMapperAction, IRowMapper<T> rowMapper = null, params object[] parameterValues)            where T : new()        {            if (rowMapper == null)            {                rowMapper = MapBuilder<T>.BuildAllProperties();            }            IParameterMapper parameterMapper = new GeneralParameterMapper(parameterMapperAction);            return db.CreateSqlStringAccessor<T>(sql, parameterMapper, rowMapper).Execute(parameterValues).ToList();        }        /// <summary>        /// 批量查询Sql并自动填充实体,如果不需要传递DbParameter,建议不要使用该方法,应使用Database.ExecuteSqlStringAccessor方法        /// </summary>        /// <typeparam name="T"></typeparam>        /// <param name="db"></param>        /// <param name="sql"></param>        /// <param name="parameterMapperAction">指定委托确认对要传递的Sql参数如何处理,该值可以传递null,为null时使用默认委托,该委托直接将parameterValues传递给cmd.Parameters.AddRange方法</param>        /// <param name="resultSetMapperFunc">指示EntLib如何填充T</param>        /// <param name="parameterValues">要传递的Sql参数,此部分对应parameterMapperAction</param>        /// <returns></returns>        public static IList<T> ExecuteBySqlString<T>(this Database db, string sql, Action<DbCommand, object[]> parameterMapperAction, Func<IDataReader, T> resultSetMapperFunc, params object[] parameterValues)        {            IParameterMapper parameterMapper = new GeneralParameterMapper(parameterMapperAction);            IResultSetMapper<T> resultSetMapper = new GeneralResultSetMapper<T>(resultSetMapperFunc);            return db.CreateSqlStringAccessor<T>(sql, parameterMapper, resultSetMapper).Execute(parameterValues).ToList();        }        /// <summary>        /// 执行SQL文本,并返回受影响行数        /// </summary>        /// <param name="db"></param>        /// <param name="sql"></param>        /// <param name="parameterSetAction"></param>        /// <returns></returns>        public static int ExecuteNonQueryBySqlString(this Database db, string sql, Action<DbCommand> parameterSetAction = null)        {            return db.ExecuteBySqlString(sql, (cmd) => { return db.ExecuteNonQuery(cmd); }, parameterSetAction);        }        /// <summary>        /// 执行SQL文本,返回DataReader        /// </summary>        /// <param name="db"></param>        /// <param name="sql"></param>        /// <param name="parameterSetAction"></param>        /// <returns></returns>        public static IDataReader ExecuteReaderBySqlString(this Database db, string sql, Action<DbCommand> parameterSetAction = null)        {            return db.ExecuteBySqlString(sql, (cmd) => { return db.ExecuteReader(cmd); }, parameterSetAction);        }        /// <summary>        /// 执行SQL文本,返回第一行第一列数据        /// </summary>        /// <param name="db"></param>        /// <param name="sql"></param>        /// <param name="parameterSetAction"></param>        /// <returns></returns>        public static object ExecuteScalarBySqlString(this Database db, string sql, Action<DbCommand> parameterSetAction = null)        {            return db.ExecuteBySqlString(sql, (cmd) => { return db.ExecuteScalar(cmd); }, parameterSetAction);        }        private static T ExecuteBySqlString<T>(this Database db, string sql, Func<DbCommand, T> resultFunc, Action<DbCommand> parameterSetAction = null)        {            var cmd = db.GetSqlStringCommand(sql);            if (parameterSetAction != null)            {                parameterSetAction(cmd);            }            return resultFunc(cmd);        }    }
顺带补充个通用的Data扩展

    /// <summary>    /// 数据相关的帮助类    /// </summary>    public static class DbHelper    {        /// <summary>        /// 从DataReader中读取可空对象        /// </summary>        /// <typeparam name="T">泛型T</typeparam>        /// <param name="dr">IDataReader</param>        /// <param name="key">Key</param>        /// <returns></returns>        public static Nullable<T> GetNullable<T>(this IDataRecord dr, string key)            where T : struct        {            return dr[key] == null || dr[key] == DBNull.Value ? (Nullable<T>)null : (T)dr[key];        }        /// <summary>        /// 当DataReader读取对象为空时,返回defaultValue        /// </summary>        /// <typeparam name="T">泛型T</typeparam>        /// <param name="dr">IDataReader</param>        /// <param name="key">Key</param>        /// <param name="defaultValue">当取到的数据为DBNull时,应当返回的默认值</param>        /// <returns></returns>        public static T GetDefaultWhileNullable<T>(this IDataRecord dr, string key, T defaultValue = default(T))        {            return dr[key] == null || dr[key] == DBNull.Value ? defaultValue : (T)dr[key];        }        /// <summary>        /// 从DataReader中读取字符串并除前后空白字符后        /// </summary>        /// <param name="dr">IDataReader</param>        /// <param name="key">Key</param>        /// <returns></returns>        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<Product> rowMapper = MapBuilder<Product>.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());            }


1 0