关于EF Unit of Work Repository的简单用法
其实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<T> GetRep<T>() where T : class; int Comment();
} public interface IRepository<T> : IQueryable<T>
where T : class
{
T Add(T obj);
}
repository我只写了一个add方法做为说明,你可以写更多的方法
public class DatabaseContext : DbContext, IUnitOfWork
{
public IRepository<T> GetRep<T>() where T : class
{
return null;
} public int Comment()
{
return this.SaveChanges();
}
}
建一个ef的context,继承DbContext的同时,实现IUnitOfWork
其中的comment方法,直接调用ef的savechanges,其实要是偷懒,直接把接口里的comment命名成savechanges就完事
剩下就是得实现这个getrep<T>的方法了。
我们对外提供的是IRepository,而我们有的是ef的DbSet,俩边接口不匹配,祭出适配器模式。
public class RepositoryAdapter<T> : IRepository<T>
where T : class
{
private DbContext context; private IDbSet<T> set; public RepositoryAdapter(DbContext context, IDbSet<T> set)
{
this.context = context;
this.set = set;
}
……
建一个适配器类,构造的时候接收context和dbset
之后,我们要实现IRepository的方法
public T Add(T obj)
{
return set.Add(obj);
}
把他导向到dbset的方法去即可
因为,我们的IRepository是集成了IQueryable的,还得实现这些
public IEnumerator<T> 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<T> GetRep<T>() where T : class
{
return new RepositoryAdapter<T>(this, this.Set<T>());
}
使用是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<T> Include<T>(this IRepository<T> source, string path) where T : class
{
var s = source as RepositoryAdapter<T>;
if (s != null)
{
return s.Set.Include(path);
}
return source;
}
为了能访问到source的dbset,我们得把dbset用只读属性公开出来。
这样,我们就可以正确的把include也导向到dbset的include了。
如果你要换orm了,你需要为新的orm开发对应的适配器类
关于EF Unit of Work Repository的简单用法的更多相关文章
- Unit of work + Repository
(Unit of work + Repository) 今日后开启进阶模式! 谈到MVC与EntityFramework,则不得不说一说事务与仓储(Unit of work + Repository) ...
- .NET MVC4 实训记录之四(Unit of work + Repository)
今日后开启进阶模式! 谈到MVC与EntityFramework,则不得不说一说事务与仓储(Unit of work + Repository). 仓储(Repository):领域对象集合.用于操作 ...
- [转]Upgrading to Async with Entity Framework, MVC, OData AsyncEntitySetController, Kendo UI, Glimpse & Generic Unit of Work Repository Framework v2.0
本文转自:http://www.tuicool.com/articles/BBVr6z Thanks to everyone for allowing us to give back to the . ...
- spring boot: @Entity @Repository一个简单的数据读存储读取
spring boot: @Entity @Repository一个简单的数据读存储读取 创建了一个实体类. 如何持久化呢?1.使用@Entity进行实体类的持久化操作,当JPA检测到我们的实体类当中 ...
- EMCA和EMCTL的简单用法
背景 其实这两个完全是两回事,不过倒是有关系,emca就是建立的资料库,建立后就用emctl来管理服务了.oem有问题基本都是重建emca,然后用emctl来操作. 当时用emca感觉真是一阵空白,太 ...
- centos shell脚本编程1 正则 shell脚本结构 read命令 date命令的用法 shell中的逻辑判断 if 判断文件、目录属性 shell数组简单用法 $( ) 和${ } 和$(( )) 与 sh -n sh -x sh -v 第三十五节课
centos shell脚本编程1 正则 shell脚本结构 read命令 date命令的用法 shell中的逻辑判断 if 判断文件.目录属性 shell数组简单用法 $( ) 和$ ...
- CATransition(os开发之画面切换) 的简单用法
CATransition 的简单用法 //引进CATransition 时要添加包“QuartzCore.framework”,然后引进“#import <QuartzCore/QuartzCo ...
- jquery.validate.js 表单验证简单用法
引入jquery.validate.js插件以及Jquery,在最后加上这个插件的方法名来引用.$('form').validate(); <!DOCTYPE html PUBLIC " ...
- NSCharacterSet 简单用法
NSCharacterSet 简单用法 NSCharacterSet其实是许多字符或者数字或者符号的组合,在网络处理的时候会用到 NSMutableCharacterSet *base = [NSMu ...
随机推荐
- day74天中间件介绍
一. importlib settings 执行结果: 两个process_request process_response按照注册顺序的倒叙进行执行 PROCESS_VIEW Process_v ...
- Mysql 练习题一
库操作: 1. 创建 数据库 create database db1; 2. 使用数据库 use db1 3. 查看表 show tables; 4. 删除 drop database db1 ...
- python scapy 网卡发包
from scapy.all import * pkt = Ether(src='11:22:33:44:55:77', dst='11:22:33:44:55:66')/ARP(op="w ...
- 二,PHP会话机制---session的基本使用
1,思考:登录网站后,在每个网页都能拿到用户信息 (1) 使用超链接传递用户名,这样太繁琐了,不建议使用 . (2) 使用数据库,每打开一个页面都查询一次用户信息表,这样网页加载速度变慢,用户体验变差 ...
- 这里给大家介绍一下通过 Wi-Fi 连接“慷慨捐赠”你的身份信息的七种方法.
这里给大家介绍一下通过 Wi-Fi 连接“慷慨捐赠”你的身份信息的七种方法和反制措施. 本文作者:黑子小盆友 1.利用免费热点 它们似乎无处不在,而且它们的数量会在接下来四年里增加三倍.但是它们当中很 ...
- iOS pods更新失败
――― TEMPLATE END ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― [!] Oh no, an erro ...
- iOS开发总结--三方平台开发之微信支付
1.前言 现在很多应用都有支付功能,支付也是开发中比较麻烦的一个部分.其实,最麻烦的部分是商户帐号的审核,如果没有商户帐号,就没有你要给钱的那个对公账户. 2.关于交易 在这个金融类项目的开发中,接触 ...
- WebDriverAPI(7)
查看页面元素的属性 测试网址 http://www.baidu.com Java语言版本API实例 @Test public void getWebElementAttribute() { dri ...
- openerp QWeb
1.web 模块 注意,OpenERP 模块中 web 部分用到的所有文件必须被放置在模块内的 static 文件夹里.这是强制性的,出于安全考虑. 事实上,我们创建的文件夹 CSS,JS 和 XML ...
- (转)Mysql常用命令行
原文:http://www.cnblogs.com/TsengYuen/archive/2012/01/11/2319034.html Mysql常用命令行 Mysql经常使用号令行大全 熬头招.my ...