仓储Repository(下)

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

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

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

  //仓储的泛型实现类
public class EFBaseRepository<TEntity> : IRepository<TEntity> where TEntity : AggregateRoot
{
[Import(typeof(IEFUnitOfWork))]
public IEFUnitOfWork UnitOfWork { get; set; } public EFBaseRepository()
{
Regisgter.regisgter().ComposeParts(this);
} public virtual IQueryable<TEntity> Entities
{
get { return UnitOfWork.context.Set<TEntity>(); }
} public virtual TEntity GetByKey(object key)
{
return UnitOfWork.context.Set<TEntity>().Find(key);
} public virtual IQueryable<TEntity> Find(Expression<Func<TEntity, bool>> express)
{
Func<TEntity, bool> lamada = express.Compile();
return UnitOfWork.context.Set<TEntity>().Where(lamada).AsQueryable<TEntity>();
} public virtual int Insert(TEntity entity)
{
UnitOfWork.RegisterNew(entity);
return UnitOfWork.Commit();
} public virtual int Insert(IEnumerable<TEntity> entities)
{
foreach (var obj in entities)
{
UnitOfWork.RegisterNew(obj);
}
return UnitOfWork.Commit();
} public virtual int Delete(object id)
{
var obj = UnitOfWork.context.Set<TEntity>().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<TEntity> entities)
{
foreach (var entity in entities)
{
UnitOfWork.RegisterDeleted(entity);
}
return UnitOfWork.Commit();
} public virtual int Delete(Expression<Func<TEntity, bool>> express)
{
Func<TEntity, bool> lamada = express.Compile();
var lstEntity = UnitOfWork.context.Set<TEntity>().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<TEntity> where TEntity : AggregateRoot
{
//........... #region 公共方法 /// <summary>
/// 根据lamada表达式查询集合
/// </summary>
/// <param name="selector">lamada表达式</param>
/// <returns></returns>
IQueryable<TEntity> Find(Expression<Func<TEntity, bool>> express); /// <summary>
/// 根据lamada表达式删除对象
/// </summary>
/// <param name="selector"> lamada表达式 </param>
/// <returns> 操作影响的行数 </returns>
int Delete(Expression<Func<TEntity, bool>> express); //..........
  }

仓储的实现

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

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

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

在菜单的仓储接口里面:

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

对应仓储实现:

  [Export(typeof(IMenuRepository))]
public class MenuRepository:EFBaseRepository<TB_MENU>,IMenuRepository
{
public IQueryable<TB_MENU> GetMenusByRole(TB_ROLE oRole)
{
var queryrole = UnitOfWork.context.Set<TB_ROLE>().AsQueryable();
var querymenu = UnitOfWork.context.Set<TB_MENU>().AsQueryable();
var querymenurole = UnitOfWork.context.Set<TB_MENUROLE>().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()的时候才会有查询等待。更多详细可以看看此文 Repository 返回 IQueryable?还是 IEnumerable?

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

 
分类: .NetC#

仓储Repository的更多相关文章

  1. C#进阶系列——DDD领域驱动设计初探(二):仓储Repository(上)

    前言:上篇介绍了DDD设计Demo里面的聚合划分以及实体和聚合根的设计,这章继续来说说DDD里面最具争议的话题之一的仓储Repository,为什么Repository会有这么大的争议,博主认为主要原 ...

  2. C#进阶系列——DDD领域驱动设计初探(三):仓储Repository(下)

    前言:上篇介绍了下仓储的代码架构示例以及简单分析了仓储了使用优势.本章还是继续来完善下仓储的设计.上章说了,仓储的最主要作用的分离领域层和具体的技术架构,使得领域层更加专注领域逻辑.那么涉及到具体的实 ...

  3. DDD领域驱动设计仓储Repository

    DDD领域驱动设计初探(二):仓储Repository(上) 前言:上篇介绍了DDD设计Demo里面的聚合划分以及实体和聚合根的设计,这章继续来说说DDD里面最具争议的话题之一的仓储Repositor ...

  4. .net core2.x - 关于仓储(Repository)

    概要:在搭建框架,顺手说下写下,关于Repository,可能你理解了,可能你还不理解,可能与不可能不是重点,重点是感兴趣就看看吧. 1.仓储(Repository)是什么? 看下翻译:仓库; 贮藏室 ...

  5. 关于一点儿对仓储(Repository)的理解

    仓储(Repository) 内容来源于dudu的 关于Repository模式一文 Repository是一个独立的层,介于领域层与数据映射层(数据访问层)之间.它的存在让领域层感觉不到数据访问层的 ...

  6. DDD领域驱动设计初探(二):仓储Repository(上)

    前言:上篇介绍了DDD设计Demo里面的聚合划分以及实体和聚合根的设计,这章继续来说说DDD里面最具争议的话题之一的仓储Repository,为什么Repository会有这么大的争议,博主认为主要原 ...

  7. DDD领域驱动设计初探(三):仓储Repository(下)

    前言:上篇介绍了下仓储的代码架构示例以及简单分析了仓储了使用优势.本章还是继续来完善下仓储的设计.上章说了,仓储的最主要作用的分离领域层和具体的技术架构,使得领域层更加专注领域逻辑.那么涉及到具体的实 ...

  8. 仓储repository概念

    1.为什么要用仓储?(仓储有什么用) 1.1 解耦 为了解耦领域层与数据映射层的关系. 1.2 管理增删查改 仓储模式最大的优点就是所有的数据访问首先是通过仓库的,对仓库的增删改都不会立即提交到数据库 ...

  9. ABP学习入门系列(三) (领域层中的仓储Repository)

    一,仓储定义:“在领域层和数据映射层的中介,使用类似集合的接口来存取领域对象”(Martin Fowler) . 仓储用来操作数据库进行数据存取.仓储接口在领域层定义,而仓储的实现类应该写在基础设施层 ...

随机推荐

  1. windows phone 墓碑化(9)

    原文:windows phone 墓碑化(9) 几个术语的理解: 名称 说明 ;        App ap = (App)Application.Current;        // 构造函数    ...

  2. Android涉及到的设计模式(转)

    1.适配器模式:ListView或GridView的Adapter 简介:不同的数据提供者使用一个适配器来向一个相同的客户提供服务. 2.建造者模式:AlertDialog.Builder 简介:可以 ...

  3. Shine we together: A innovative dating site using 2012 Nobel Laureate Roth's algorithm

    Abstract Our dating site introduced scoring and its related functionalities innovatively, conforming ...

  4. Java学习之路:详细解释Java解析XML四种方法

    XML如今已经成为一种通用的数据交换格式,它的平台无关性,语言无关性,系统无关性,给数据集成与交互带来了极大的方便. 对于XML本身的语法知识与技术细节,须要阅读相关的技术文献,这里面包含的内容有DO ...

  5. JavaScript模式读书笔记 文章3章 文字和构造

    1.对象字面量     -1.Javascript中所创建的自己定义对象在任务时候都是可变的.能够从一个空对象開始,依据须要添加函数.对象字面量模式能够使我们在创建对象的时候向其加入函数.       ...

  6. SendMail如何签名

    MailAddress类有两个参数 第1个参数:发送者的邮箱 第2个参数:发送者的签名 示例: MailMessage message = new MailMessage();message.From ...

  7. android存储阵列数据SharedPreferences

    假设要数组数据(如boolean[] .int[]等)到SharedPreferences时,我们能够先将数组数据组织成json数据存储到SharedPreferences,读取时则对json数据进行 ...

  8. Duanxx的STM32学习: 启动模式,BOOT0和BOOT1具体解释

    在画STM32的电路图的时候,关于STM32的启动方式纠结了一下,现有的參考设计都是在STM32的启动选择引脚BOOT0和BOOT1上使用了跳帽,用以人工选择STM32的启动方式,可是在实际应用中这样 ...

  9. 【Linux探索之旅】第二部分第一课:终端Terminal,好戏上场

    内容简介 1.第二部分第一课:终端Terminal,好戏上场 2.第二部分第二课预告:命令行,世界尽在掌握 终端Terminal,好戏上场 随着第一部分的结束,我们进入了第二部分(小编你这好像是废话. ...

  10. 新手学Unity3d的一些网站及相应学习路线

    一.unity3d有什么优势 如果您对开发游戏感兴趣,而又没有决定选择哪一个游戏引擎,别犹豫了 unity3d是一个很好的选择! 就我来看unity3d优势主要有以下几方面:首先部署简单,自带了一个I ...