我的开发框架(WinForm)2

本文详细介绍了一个ORM框架的设计理念,包括核心模块的接口定义与实现,如IRepository、IUnitOfWork及IDbCnnFactory等,同时提供了具体的代码示例。

上篇文章简单的介绍了一下,我的一个开发框架。看的人还不少,多谢大家的关注,我继续介绍一下,模块和模块之间是怎么组织起来的。

Data模块:

该模块主要完成对数据的操作,采用仓储模式实现,在核心模块(Core.Data)中定义操作接口和基础类. 主要的接口有IRepository,IUnitOfWork,IDbCnnFactory。

所有的数据库操作都是针对实体进行的,一个实体在数据库中对应一个比,目前为了简化操作,不考虑实体关联的操作。这样更加容易理解,更容易上手。

一、接口的定义

1、IRepository接口,最基本、最重要的接口。通过它完成实体类的增删改查的操作。

 
IRepository/// <summary>
   /// Interface IRepository
   /// </summary>
   /// <typeparam name="T">业务实体</typeparam>
   /// <typeparam name="Tid">业务实体的主键类型</typeparam>
   public interface IRepository<T, Tid> where T : EntityBase<Tid>, new()
   {
       /// <summary>
       /// 添加数据
       /// </summary>
       /// <param name="entity">The entity.</param>
       void Add(T entity);

       /// <summary>
       /// 批量添加数据
       /// </summary>
       /// <param name="entities">The entities.</param>
       void Add(IEnumerable<T> entities);

       /// <summary>
       /// 更新数据
       /// </summary>
       /// <param name="entity">The entity.</param>
       void Update(T entity);

       /// <summary>
       /// 批量更新数据
       /// </summary>
       /// <param name="entities">The entities.</param>
       void Update(IEnumerable<T> entities);

       /// <summary>
       /// Delete item
       /// </summary>
       /// <param name="entity">The entity.</param>
       void Delete(T entity);

       /// <summary>
       /// 批量删除数据
       /// </summary>
       /// <param name="entities">The entities.</param>
       void Delete(IEnumerable<T> entities);

       /// <summary>
       /// 根据主键删除数据
       /// </summary>
       /// <param name="id">The id.</param>
       void DeleteByID(object id);

       /// <summary>
       /// 删除符合条件的实体
       /// </summary>
       /// <param name="filter"></param>
       void Delete(Expression<Func<T, bool>> filter);

       /// <summary>
       /// 根据主键批量删除数据
       /// </summary>
       /// <param name="ids">The ids.</param>
       void DeleteByIDs(IEnumerable<Tid> ids);
       /// <summary>
       /// 通过ID读取数据
       /// </summary>
       /// <param name="id">The id.</param>
       /// <returns>`0.</returns>
       T GetEntityByID(object id);

       /// <summary>
       /// 获得符合条件的第一个实体
       /// </summary>
       /// <param name="filter"></param>
       T GetEntity(Expression<Func<T, bool>> filter);

       /// <summary>
       /// 开始一个工作单元
       /// </summary>
       /// <returns>IUnitOfWork.</returns>
       IUnitOfWork OpenUnitOfWork();

       /// <summary>
       /// 读取全部数据
       /// </summary>
       /// <returns>List of selected elements</returns>
       IEnumerable<T> GetEntities();


       /// <summary>
       /// 根据过滤条件读取数据
       /// </summary>
       /// <param name="filter">过滤条件</param>
       /// <returns>List of selected elements</returns>
       IEnumerable<T> GetEntities(Expression<Func<T, bool>> filter);

       /// <summary>
       /// 根据过滤条件和排序条件读取数据
       /// </summary>
       /// <typeparam name="S"></typeparam>
       /// <param name="filter">过滤条件</param>
       /// <param name="orderByExpression">排序条件</param>
       /// <param name="ascending">是否为正序</param>
       /// <returns>IEnumerable{`0}.</returns>
       IEnumerable<T> GetEntities<S>(Expression<Func<T, bool>> filter,
           Expression<Func<T, S>> orderByExpression, bool ascending = true);

       /// <summary>
       /// 分页读取数据
       /// </summary>
       /// <param name="pageIndex">页号</param>
       /// <param name="pageSize">每页大小</param>
       /// <returns>List of selected elements</returns>
       PageResult<T> GetPagedEntities(int pageIndex, int pageSize);

       /// <summary>
       /// 分页读取数据
       /// </summary>
       /// <param name="filter">过滤条件</param>
       /// <param name="pageIndex">页号</param>
       /// <param name="pageSize">每页大小</param>
       /// <returns>List of selected elements</returns>
       PageResult<T> GetPagedEntities(Expression<Func<T, bool>> filter, int pageIndex, int pageSize);

       /// <summary>
       /// 分页读取数据
       /// </summary>
       /// <typeparam name="S"></typeparam>
       /// <param name="filter">过滤条件</param>
       /// <param name="orderByExpression">排序条件</param>
       /// <param name="ascending">是否正序</param>
       /// <param name="pageIndex">页号</param>
       /// <param name="pageSize">每页大小</param>
       /// <returns>List of selected elements</returns>
       PageResult<T> GetPagedEntities<S>(Expression<Func<T, bool>> filter, Expression<Func<T, S>> orderByExpression, bool ascending, int pageIndex, int pageSize);

       /// <summary>
       /// 分页读取数据
       /// </summary>
       /// <param name="filter">sql过滤条件</param>
       /// <param name="pageIndex">页号</param>
       /// <param name="pageSize">每页大小</param>
       /// <returns>PageResult{`0}.</returns>
       PageResult<T> GetPagedEntities(string filter, int pageIndex, int pageSize);

       /// <summary>
       /// 分页读取数据
       /// </summary>
       /// <param name="filter">sql过滤条件</param>
       /// <param name="orderby">sql排序字段</param>
       /// <param name="pageIndex">页号</param>
       /// <param name="pageSize">每页大小</param>
       /// <returns>PageResult{`0}.</returns>
       PageResult<T> GetPagedEntities(string filter, string orderby, int pageIndex, int pageSize);

   }
2、其中实体类必须继承EntityBase<Tid>或 EntityBase 类,TId 是指ID的类型,每个实体必须有个主键Id,
EntityBase [Serializable]
    public class EntityBase<Tid>
    {
        /// <summary>
        /// 唯一主键
        /// </summary>
        /// <value>The id.</value>
        public Tid Id { get; set; }

        #region Override
        /// <summary>
        /// <see cref="M:System.Object.GetHashCode"/>
        /// </summary>
        /// <returns><see cref="M:System.Object.GetHashCode"/></returns>
        public override int GetHashCode()
        {
            if (this.Id.Equals(null))
            {
                return base.GetHashCode();
            }
            else
                return this.Id.GetHashCode() ^ 31;
               
        }
        /// <summary>
        /// Determines whether the specified <see cref="System.Object" /> is equal to this instance.
        /// </summary>
        /// <param name="obj">与当前的 <see cref="T:System.Object" /> 进行比较的 <see cref="T:System.Object" />。</param>
        /// <returns><c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.</returns>
        public override bool Equals(object obj)
        {
            if (obj == null || !(obj is EntityBase<Tid>))
                return false;

            if (Object.ReferenceEquals(this, obj))
                return true;

            EntityBase<Tid> item = (EntityBase<Tid>)obj;
            return item.Id.Equals(this.Id);
        }

        /// <summary>
        /// Implements the ==.
        /// </summary>
        /// <param name="left">The left.</param>
        /// <param name="right">The right.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator ==(EntityBase<Tid> left, EntityBase<Tid> right)
        {
            if (Object.Equals(left, null))
                return (Object.Equals(right, null)) ? true : false;
            else
                return left.Equals(right);
        }

        /// <summary>
        /// Implements the !=.
        /// </summary>
        /// <param name="left">The left.</param>
        /// <param name="right">The right.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator !=(EntityBase<Tid> left, EntityBase<Tid> right)
        {
            return !(left == right);
        }
        #endregion
    }

    3、IDbCnnFactory接口主要完成数据库连接的维护工作

IDbCnnFactory /// <summary>
    /// Interface IDbCnnFactory
    /// </summary>
    public interface IDbCnnFactory
    {
        /// <summary>
        /// 默认的数据库键值,多数据库时用
        /// </summary>
        string DefaultDbKey { get; }

        /// <summary>
        /// 数据库提供者
        /// </summary>
        /// <value>The db provider.</value>
        string DbProvider { get; }

        /// <summary>
        /// 打开一个数据库连接
        /// </summary>
        /// <returns>IDbConnection.</returns>
        IDbConnection OpenConnection(string dbKey="");
        /// <summary>
        /// 创建一个数据库连接
        /// </summary>
        /// <returns>IDbConnection.</returns>
        IDbConnection CreateConnection(string dbKey="");
    }

    4、IUnitOfWork接口主要实现将多个数据库操作组合成一个工作单元, 对数据库来说就是一个事务。

IUnitOfWork /// <summary>
    /// Interface IUnitOfWork
    /// </summary>
    public interface IUnitOfWork : IDisposable
    {
        /// <summary>
        /// 提交更改
        /// </summary>
        void Commit();

        /// <summary>
        /// Begins the transition.
        /// </summary>
        /// <returns>IDisposable.</returns>
        IDisposable BeginTransition();
        /// <summary>
        /// 撤销更改
        /// </summary>
        void Rollback();
    }

 

另外还有几个辅助的接口,同样是在Core.Data中定义

     ISqlRepository:类似于以前的SQLHelper类,它里面只是定义了一些执行sql的方法。

     ITableManager :用于数据表的维护。新建、删除、重建表操作。
     PageResult<TEntity>:分页结果类,主要保存 共有多少页,当前第几页,以及当前页的数据。

     UnitOfWork类:IUnitOfWork接口的实现类。

     IStatRepository:简单的数据统计.

二、接口的实现

Data.Oracle是针对Oracle数据库的一个实现。

image

Repository类实现了一下接口一个是默认ID类型的,一个是可自定义ID类型的.

public class Repository<TEntity, Tid> : IRepository<TEntity, id>,IStatRepository<TEntity,Tid>,ISqlRepository 
where TEntity : EntityBase<Tid>, new()
 
public class Repository<TEntity> : Repository<TEntity, Guid>, IRepository<TEntity>, IStatRepository<TEntity>
 where TEntity : EntityBase, new()
   

OracleDbCnnFactory 实现就比较简单了,和写ADO.Net一样.唯一注意的就是增加了MEF的导出标签

 [Export(typeof(IDbCnnFactory))] ,MEF的使用,园子里有很多好的文章,我就不班门弄斧了

 

三、接口的使用

     比如我设计了一个菜单类,属性主要有显示的标题、关键字、序号等。

//获得菜单类操作的Repository
   var rep = ApplicationEx.Container.GetRepository<MenuInfo>();
   //查询所有可用的菜单,并排序
var ens=  rep.GetEntities(t => t.Enable == true).OrderBy(t=>t.PIndex);
返回的是 IEnumerable<MenuInfo>
 
关于ApplicationEx类,我们后面会介绍到。
通过以上这些接口,我相信90%的数据库操作,都能满足。如果你的系统对性能要求比较高的话,我建议直接写sql+ADO.Net写,执行效率会更好,也好优化。

我这样设计也考虑到Web程序的应用,毕竟程序能在web、手机上实现的都会移植过去,单机的项目会越来越少。

转载于:https://www.cnblogs.com/liuyh208/p/3284319.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值