博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C#进阶系列——DDD领域驱动设计初探(三):仓储Repository(下)
阅读量:7237 次
发布时间:2019-06-29

本文共 5619 字,大约阅读时间需要 18 分钟。

前言:上篇介绍了下仓储的代码架构示例以及简单分析了仓储了使用优势。本章还是继续来完善下仓储的设计。上章说了,仓储的最主要作用的分离领域层和具体的技术架构,使得领域层更加专注领域逻辑。那么涉及到具体的实现的时候我们应该怎么做呢,本章就来说说仓储里面具体细节方便的知识。

DDD领域驱动设计初探系列文章:

一、对仓储接口以及实现基类的完善

1、仓储实现基类的所有方法加上virtual关键字,方便具体的仓储在特定需求的时候override基类的方法。

  //仓储的泛型实现类    public class EFBaseRepository
: IRepository
where TEntity : AggregateRoot { [Import(typeof(IEFUnitOfWork))] public IEFUnitOfWork UnitOfWork { get; set; } public EFBaseRepository() { Regisgter.regisgter().ComposeParts(this); } public virtual IQueryable
Entities { get { return UnitOfWork.context.Set
(); } } public virtual TEntity GetByKey(object key) { return UnitOfWork.context.Set
().Find(key); } public virtual IQueryable
Find(Expression
> express) { Func
lamada = express.Compile(); return UnitOfWork.context.Set
().Where(lamada).AsQueryable
(); } public virtual int Insert(TEntity entity) { UnitOfWork.RegisterNew(entity); return UnitOfWork.Commit(); } public virtual int Insert(IEnumerable
entities) { foreach (var obj in entities) { UnitOfWork.RegisterNew(obj); } return UnitOfWork.Commit(); } public virtual int Delete(object id) { var obj = UnitOfWork.context.Set
().Find(id); if (obj == null) { return 0; } UnitOfWork.RegisterDeleted(obj); return UnitOfWork.Commit(); } public virtual int Delete(TEntity entity) { UnitOfWork.RegisterDeleted(entity); return UnitOfWork.Commit(); } public virtual int Delete(IEnumerable
entities) { foreach (var entity in entities) { UnitOfWork.RegisterDeleted(entity); } return UnitOfWork.Commit(); } public virtual int Delete(Expression
> express) { Func
lamada = express.Compile(); var lstEntity = UnitOfWork.context.Set
().Where(lamada); foreach (var entity in lstEntity) { UnitOfWork.RegisterDeleted(entity); } return UnitOfWork.Commit(); } public virtual int Update(TEntity entity) { UnitOfWork.RegisterModified(entity); return UnitOfWork.Commit(); } }

 

2、查询和删除增加了传参lamada表达式的方法

仓储接口:

  public interface IRepository
where TEntity : AggregateRoot { //........... #region 公共方法 ///
/// 根据lamada表达式查询集合 /// ///
lamada表达式 ///
IQueryable
Find(Expression
> express); ///
/// 根据lamada表达式删除对象 /// ///
lamada表达式 ///
操作影响的行数
int Delete(Expression
> express); //..........  }

仓储的实现

   //仓储的泛型实现类    public class EFBaseRepository
: IRepository
where TEntity : AggregateRoot { //............. public virtual IQueryable
Find(Expression
> express) { Func
lamada = express.Compile(); return UnitOfWork.context.Set
().Where(lamada).AsQueryable
(); } public virtual int Delete(Expression
> express) { Func
lamada = express.Compile(); var lstEntity = UnitOfWork.context.Set
().Where(lamada); foreach (var entity in lstEntity) { UnitOfWork.RegisterDeleted(entity); } return UnitOfWork.Commit(); } //............. }

增加这两个方法之后,对于单表的一般查询都可以直接通过lamada表示式的方法传入即可,并且返回值为IQueryable类型。

 

3、对于涉及到多张表需要连表的查询机制,我们还是通过神奇的Linq来解决。例如我们有一个通过角色取角色对应的菜单的接口需求。

在菜单的仓储接口里面:

   ///     /// 菜单这个聚合根的仓储接口    ///     public interface IMenuRepository:IRepository
{ IQueryable
GetMenusByRole(TB_ROLE oRole); }

对应仓储实现:

  [Export(typeof(IMenuRepository))]    public class MenuRepository:EFBaseRepository
,IMenuRepository { public IQueryable
GetMenusByRole(TB_ROLE oRole) { var queryrole = UnitOfWork.context.Set
().AsQueryable(); var querymenu = UnitOfWork.context.Set
().AsQueryable(); var querymenurole = UnitOfWork.context.Set
().AsQueryable(); var lstres = from menu in querymenu from menurole in querymenurole from role in queryrole where menu.MENU_ID == menurole.MENU_ID && menurole.ROLE_ID == role.ROLE_ID && role.ROLE_ID == oRole.ROLE_ID select menu; return lstres; } }

 这里也是返回的IQueryable接口的集合,千万不要小看IQueryable接口,它是一种表达式树,可以延迟查询。也就是说,在我们执行GetMenusByRole()之后,得到的是一个带有查询sql语句的表达式树结构,并没有去数据库执行查询,只有在我们ToList()的时候才会去查询数据库。我们来写个Demo测试下。

   class Program    {        [Import]        public IUserRepository userRepository { get; set; }        [Import]        public IMenuRepository menuRepository { get; set; }        static void Main(string[] args)        {            //注册MEF            var oProgram = new Program();            Regisgter.regisgter().ComposeParts(oProgram);var lstFindUsers = oProgram.userRepository.Find(x => x.USER_NAME !=null);            var lstRes = lstFindUsers.ToList();            var lstMenu = oProgram.menuRepository.GetMenusByRole(new TB_ROLE() { ROLE_ID = "aaaa" });            var lstMenuRes = lstMenu.ToList();        }    }

来看执行过程:

 当程序执行var lstMenu = oProgram.menuRepository.GetMenusByRole(new TB_ROLE() { ROLE_ID = "aaaa" })这一步的时候基本是不耗时的,因为这一步仅仅是在构造表达式树,只有在.ToList()的时候才会有查询等待。更多详细可以看看此文 。

在dax.net的系列文章中,提到了规约模式的概念,用于解决条件查询的问题。博主感觉这个东西设计确实牛叉,但实用性不太强,一般中小型的项目也用不上。有兴趣可以看看。

转载地址:http://yarfm.baihongyu.com/

你可能感兴趣的文章
江山代有才人出 | 微软亚洲研究院建院二十周年
查看>>
Linux安装gitlab
查看>>
java源码-synchronized
查看>>
PostgreSQL 10.1 手册_部分 III. 服务器管理_第 21 章 数据库角色_21.2. 角色属性
查看>>
《刻意练习》读后感
查看>>
DataWorks V2.0 系列公开课
查看>>
使用 logstash, elasticsearch, kibana 搭建日志分析系统
查看>>
Android Q 将获得大量的隐私保护功能
查看>>
《恋恋笔记本》观后感
查看>>
Spring源码剖析6:Spring AOP概述
查看>>
Maven的POM.xml配置大全
查看>>
SmartRefreshLayout + BaseRecyclerviewAdapterHelper 使用MVP方式实现下拉刷新
查看>>
详解KVC(转载)
查看>>
tp5 发送阿里云短信
查看>>
cookie java spring
查看>>
Thrift之TProcess类体系原理及源码详细解析
查看>>
python写的一段分页的代码
查看>>
阿里巴巴数学大赛赛题公布,你敢来挑战吗?(含参考答案)
查看>>
设计模式六大原则(1):单一职责原则
查看>>
ubnutu日常使用软件
查看>>