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

虽然标题是对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的扩展,以下是具体代码,因个人喜好问题,没封装对应Proc的扩展方法,其实代码都一样

    /// <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();
        }
    }

顺带补充个通用的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 [email protected]";

            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());
            }
时间: 2024-10-07 04:35:14

微软企业库6 Data Access Application Block 扩展的相关文章

[EntLib]微软企业库6 基于Data Access Application Block的Repository

名字起得有点夸张了,其实就是实现基于Data Access Application Block的DAL基类和约束 首先Repository部分没什么好描述的,如果有不了解的可以直接百度或者谷歌相关内容,直接上具体代码 注意此部分没有写批量查询的方法(比如FindAll,这跟后面的基类设定有关) /// <summary> /// DataAccess Repository /// </summary> /// <typeparam name="T1">

Enterprise Library - Data Access Application Block 6.0.1304

Enterprise Library - Data Access Application Block 6.0.1304 企业库,数据访问应用程序块 6.0.1304 企业库的数据访问应用程序块的任务简化了开发实现通用数据访问功能. 应用程序可以使用这个应用程序块在不同的情况下,例如读取数据显示,通过应用程序层传递数据,提交更改的数据的数据库系统. 安装企业库,数据访问应用程序块,运行以下命令 包管理器控制台 PM> Install-Package EnterpriseLibrary.Data h

学习Microsoft EnterpriseLibrary 5.0 之 Data Access Application Block

微软为开发人员提供了企业库,用于错误处理.日志记录.AOP.数据库访问.权限控制等功能.这里使用数据库访问模块来实现对Sql Server的数据库访问. 首先打开安装目录下的EntLibConfig.exe配置程序,选择Add Data Settings 可以设置连接字符串名称.连接字符串内容和连接数据库的类型.设置好以后保存为配置文件,配置文件的内容为: 1 <?xml version="1.0" encoding="utf-8" ?> 2 <c

微软企业库DBBA的研究

Summary:如何入门使用Data Access Application Block,可以参考Enterprise Library 3.1中文帮助:数据访问应用程序块.这篇文章侧重在DAAB工作原理.代码结构上的一些注解. DAAB中抽象类Database提供了针对数据库操作的接口,从它派生出来的各个数据库类使用工厂方式创建.我们可以基于这个机制进行扩展,实现对其它数据库的支持,例如:Ent Lib 2.0 DAAB添加MySql扩展 MySql5.0.27+MySql .Net Connec

在数据库访问项目中使用微软企业库Enterprise Library,实现多种数据库的支持

在我们开发很多项目中,数据访问都是必不可少的,有的需要访问Oracle.SQLServer.Mysql这些常规的数据库,也有可能访问SQLite.Access,或者一些我们可能不常用的PostgreSQL.IBM DB2.或者国产达梦数据库等等,这些数据库的共同特点是关系型数据库,基本上开发的模型都差不多,不过如果我们基于ADO.NET的基础上进行开发的话,那么各种数据库都有自己不同的数据库操作对象,微软企业库Enterprise Library是基于这些不同数据库的操作做的抽象模型,适合多数据

微软企业库的Cache

微软企业库的Cache 通常,应用程序可以将那些频繁访问的数据,以及那些需要大量处理时间来创建的数据存储在内存中,从而提高性能.基于微软的企业库,我们的快速创建一个缓存的实现. 新建PrismSample.Infrastructure.Cache 新建一个类库项目,将其命名为PrismSample.Infrastructure.Cache,然后从nuget中下载微软企业库的Cache. 然后新建我们的CacheManager类: using Microsoft.Practices.Enterpr

微软企业库5.0学习笔记(10)ASP.NET模块依赖注入

您可以使用HTTP模块,一个到ASP.NET HttpApplicationState类的扩展,在Global.asax编写代码强制ASP.NET在每一个页面请求时自动注入依赖的对象,就像在ASP.NET Web窗体应用程序中讨论的一样. 下列方法显示了一个合适的方法能够获取PreRequestHandlerExecute事件将它自己注入到ASP.NET的执行流水线,在每个页面请求中通过容器的BuildUp方法运行Http模块,并获取OnPageInitComplete事件.当OnPageIni

微软企业库5.0 支持 MySql

三步让 企业库支持 mysql 数据库 1.创建 MySqlDatabaseData 类 using Microsoft.Practices.EnterpriseLibrary.Common.Configuration; using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ContainerModel; using Microsoft.Practices.EnterpriseLibrary.Data; using Mi

使用Microsoft EnterpriseLibrary(微软企业库)日志组件把系统日志写入数据库和xml文件

这里只是说明在项目中如何配置使用微软企业库的日志组件,对数据库方面的配置请参考其他资料. 1.在项目中添加Microsoft.Practices.EnterpriseLibrary.Data.dll.Microsoft.Practices.EnterpriseLibrary.Logging.dll.Microsoft.Practices.EnterpriseLibrary.Logging.Database.dll这三个引用. 2.打开EnterpriseLibrary的配置工具EntLibCon