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

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数据库的一个实现。

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、手机上实现的都会移植过去,单机的项目会越来越少。

我的开发框架(WinForm)2的更多相关文章

  1. 开发框架(WinForm)3

    我的开发框架(WinForm)3 今天继续给大家介绍核心库的IOC的使用,在我的框架里,IOC使用的比较简单,主要是用于解除模块间的耦合和实例化接口. 1.接口说明,IocContainer接口比较简 ...

  2. RDIFramework.NET敏捷开发框架WinForm新增文件中心-实现附件集中管理

    1.引言 文件中心类似附件管理是一个非常实用功能,可以归档自己平时所需要的文件,也可以把文件分享给别人,更像一个知识中心.文件中心主界面如下图所示,左侧"附件分类"展示了用户对文件 ...

  3. 我的开发框架(WinForm)

    近来,看园子里,好多同学,展示自己工作中的开发框架,有的功能强大,有的短小精悍,我也来凑个热闹,望各位大侠指点一二. 一.指导思想 1.尽量减少程序员对数据库的依赖,或者说尽力少的写sql 语句.根据 ...

  4. 我的开发框架(WinForm)4

    日志模块 对于一个系统来说,日志模块是必不可少的,它能给后面系统的维护和bug的修复,带来极大的方便..net的日志模块有很多,比较流行的有Log4Net,NLog,还有微软企业库的日志模块,我采用的 ...

  5. 我的开发框架(WinForm)3

    今天继续给大家介绍核心库的IOC的使用,在我的框架里,IOC使用的比较简单,主要是用于解除模块间的耦合和实例化接口. 1.接口说明,IocContainer接口比较简单只有3个方法,但是是系统中用的最 ...

  6. WinForm开发中通用附件管理控件设计开发参考

    1.引言 在WinForm开发中,文件附件的管理几乎在任何一个应用上都会存在,是一个非常通用集中的公共模块.我们日常记录会伴随着有图片.文档等附件形式来展现,如果为每个业务对象都做一个附件管理,或者每 ...

  7. RDIFramework.NET ━ .NET敏捷开发框架全新发布-最好用的.NET开发框架 100%源码授权

    RDIFramework.NET,基于.NET的快速信息化系统敏捷开发框架.10年沉淀.历经上千项目检验,致力于企业智能化开发,帮助提升软件开发效率.最好用的.NET开发框架,100%源码授权. 1. ...

  8. RDIFramework.NET敏捷开发框架 ━ 工作流程组件介绍

    RDIFramework.NET,基于.NET的快速信息化系统敏捷开发.整合框架,给用户和开发者最佳的.Net框架部署方案. 1.RDIFramework.NET敏捷开发框架介绍 RDIFramewo ...

  9. RDIFramework.NET敏捷开发框架Web新增邮件中心实现便捷式的邮件收发

    1.引言 邮件收发在很多业务系统中都有这样的需求,是比较正式和常用的功能.在我们的框架中提供了邮件中心功能模块,集内部邮件的收发.邮件归类.邮件星标的标记.邮件的删除与彻底删除等,邮件中心功能模块界面 ...

随机推荐

  1. 单点登录技术:微软Passport单点登录协议和自由联盟规范

    随着互联网络应用的普及,越来越多的人开始使用互联网上提供的服务.然而目前提供服务的网站大多采用用户名.口令的方式来识别用户身份,这使得用户需要经常性的输入自己的用户名.口令.显然这种认证方式存在着弊端 ...

  2. STM32学习笔记——FSMC 驱动大容量NAND FLASH [复制链接]

    本文原创于观海听涛,原作者版权所有,转载请注明出处. 近几天开发项目需要用到STM32驱动NAND FLASH,但由于开发板例程以及固件库是用于小页(512B),我要用到的FLASH为1G bit的大 ...

  3. Matlab GUI界面

    做SVD的时候,看学姐的demo,用到了matlab的GUI,感兴趣就自己学了一下: 从简单的例子说起吧. 创建Matlab GUI界面通常有两种方式: 1,使用 .m 文件直接动态添加控件     ...

  4. 【OpenGL】画立方体

    编写一个程序,该程序运行时可以用鼠标的一个按键调整立方体的方向,用另一个按键平移立方体,用第三个按键缩放立方体. 这是题目,我的程序不一定完全按照这个来.初学OpenGL,对那一堆坐标系表示十分混乱, ...

  5. leetcode@ [303/304] Range Sum Query - Immutable / Range Sum Query 2D - Immutable

    https://leetcode.com/problems/range-sum-query-immutable/ class NumArray { public: vector<int> ...

  6. lazyload 图片延迟加载

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. Jquery ajax 得到返回值

    Jquery ajax 得到返回值 1.ajax默认是异步调用的,所以得到的返回值是空值,要得到值必须改成同步:async: false,//同步. 2.必须定义一个全局变量 var result = ...

  8. 如何对SQL Server 2005进行设置以允许远程连接(转载)

    如何对SQL Server 2005进行设置以允许远程连接(转载) 在尝试从远程计算机连接到 Microsoft SQL Server 2005 实例时,可能会接收到错误消息.在使用任何程序连接到 S ...

  9. MySQL索引使用方法和性能优化

    在自己的一个项目中,数据比较多,搜索也很频繁,这里找到一个建立索引很不错的文章,推荐下. 关于MySQL索引的好处,如果正确合理设计并且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的 ...

  10. 汽车行业的DMS系统 IT不变应万变

    DMS是针对4S店的整车销售.零配件仓库.售后维修服务(含车间管理).客服服务涵盖4S店业务进行完整管理的系统,是对销售.维修.客户关系进行一系列的整合.其中,服务的预约.进店接待都有着跟踪处理,客户 ...