博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于EF Unit of Work Repository的简单用法
阅读量:6948 次
发布时间:2019-06-27

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

其实ef本身就是unit of work+repository的

其中继承自DbContext的类就是unit of work

context中的DbSet<T>属性就是repository,你也可以不建那些属性,而使用context.Set<T>来获取一个DbSet<T>

 

如果直接在逻辑层就ef了,一来可能觉得会与ef绑的太紧,二来可能mock的难度会变大。所以有时候还是希望逻辑层引用的是自己定义的unit of work接口和repository接口

先来看这两个接口吧

public interface IUnitOfWork{    IRepository
GetRep
() where T : class; int Comment();}public interface IRepository
: IQueryable
where T : class{ T Add(T obj);}
 
repository我只写了一个add方法做为说明,你可以写更多的方法
public class DatabaseContext : DbContext, IUnitOfWork{    public IRepository
GetRep
() where T : class { return null; } public int Comment() { return this.SaveChanges(); }}
建一个ef的context,继承DbContext的同时,实现IUnitOfWork
其中的comment方法,直接调用ef的savechanges,其实要是偷懒,直接把接口里的comment命名成savechanges就完事
剩下就是得实现这个getrep
的方法了。
 
我们对外提供的是IRepository,而我们有的是ef的DbSet,俩边接口不匹配,祭出适配器模式。
 
public class RepositoryAdapter
: IRepository
where T : class{ private DbContext context; private IDbSet
set; public RepositoryAdapter(DbContext context, IDbSet
set) { this.context = context; this.set = set; }

……

建一个适配器类,构造的时候接收context和dbset

之后,我们要实现IRepository的方法

 

public T Add(T obj){    return set.Add(obj);}

把他导向到dbset的方法去即可

因为,我们的IRepository是集成了IQueryable的,还得实现这些

public IEnumerator
GetEnumerator(){ return set.GetEnumerator();}IEnumerator IEnumerable.GetEnumerator(){ return this.GetEnumerator();}public Expression Expression{ get { return set.Expression; }}public Type ElementType{ get { return set.ElementType; }}public IQueryProvider Provider{ get { return set.Provider; }}

统统导向到dbset的方法去

我们让context的方法返回这个适配器

 

public IRepository
GetRep
() where T : class{ return new RepositoryAdapter
(this, this.Set
());}

使用是uow.GetRep<T>().Where(x=>x…….)各种where,first,count,any,只要是IQueryable支持的都可以正常使用

并且根据你IRepository中定义的方法,还可以add,delete之类的

 

但是有一个ef的方法在这里是不行的,那就是Include。

普通的where之类的方法,看源码

他是用source的provider去走。

这里,source是我们的IRepository,实际是RepositoryAdapter,adapter中的provider,我们返回的是dbset的provider,所以他可以正常的走到dbset去查库

但是,我们看include

include 并没有走provider,而是要看source是不是DbQuery<T>或者ObjectQuery<T>,我们这里自然都不是,所以include没能正确的导向到dbset的include去

我们可以自己写一个扩展方法

public static IQueryable
Include
(this IRepository
source, string path) where T : class{ var s = source as RepositoryAdapter
; if (s != null) { return s.Set.Include(path); } return source;}

为了能访问到source的dbset,我们得把dbset用只读属性公开出来。

这样,我们就可以正确的把include也导向到dbset的include了。

 

如果你要换orm了,你需要为新的orm开发对应的适配器类

转载于:https://www.cnblogs.com/czcz1024/p/4089589.html

你可能感兴趣的文章
IT思想类智力题
查看>>
php设计模式-单例模式
查看>>
php扩展php-redis安装与使用
查看>>
python一天一题(2)
查看>>
[HTML5] Semantics for accessibility
查看>>
Win10下安装Ubuntu16.04虚拟机并搭建TensorFlow1.3环境
查看>>
leetcode 108. Convert Sorted Array to Binary Search Tree
查看>>
【商城购物车】购物车逻辑
查看>>
PCIE协议解析 synopsys IP loopback 读书笔记(1)
查看>>
关于小程序你需要知道的事
查看>>
表服务器无法打开与报表服务器数据库的连接。所有请求和处理都要求与数据库建立连接...
查看>>
4月第4周业务风控关注 | 网络犯罪经济每年1.5万亿美元 GDP居全球第12位
查看>>
idea中gitlab新创建分支查找不到的原因
查看>>
php调试时echo,print_r(),var_dump()的区别
查看>>
vue 作用域插槽
查看>>
tfs 2013 利用 web deploy 完成asp.net站点自动发布
查看>>
dom对象常用的属性和方法有哪些?
查看>>
C#遍历XmlDocument对象所有节点名称、类型、属性(Attribute)
查看>>
范畴论-一个单子(Monad)说白了不过就是自函子范畴上的一个幺半群而已
查看>>
Spring cloud系列之Zuul配置项中sensitiveHeaders和ignoredHeaders
查看>>