其实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的简单用法的更多相关文章

  1. Unit of work + Repository

    (Unit of work + Repository) 今日后开启进阶模式! 谈到MVC与EntityFramework,则不得不说一说事务与仓储(Unit of work + Repository) ...

  2. .NET MVC4 实训记录之四(Unit of work + Repository)

    今日后开启进阶模式! 谈到MVC与EntityFramework,则不得不说一说事务与仓储(Unit of work + Repository). 仓储(Repository):领域对象集合.用于操作 ...

  3. [转]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 . ...

  4. spring boot: @Entity @Repository一个简单的数据读存储读取

    spring boot: @Entity @Repository一个简单的数据读存储读取 创建了一个实体类. 如何持久化呢?1.使用@Entity进行实体类的持久化操作,当JPA检测到我们的实体类当中 ...

  5. EMCA和EMCTL的简单用法

    背景 其实这两个完全是两回事,不过倒是有关系,emca就是建立的资料库,建立后就用emctl来管理服务了.oem有问题基本都是重建emca,然后用emctl来操作. 当时用emca感觉真是一阵空白,太 ...

  6. centos shell脚本编程1 正则 shell脚本结构 read命令 date命令的用法 shell中的逻辑判断 if 判断文件、目录属性 shell数组简单用法 $( ) 和${ } 和$(( )) 与 sh -n sh -x sh -v 第三十五节课

    centos   shell脚本编程1 正则  shell脚本结构  read命令  date命令的用法  shell中的逻辑判断  if 判断文件.目录属性  shell数组简单用法 $( ) 和$ ...

  7. CATransition(os开发之画面切换) 的简单用法

    CATransition 的简单用法 //引进CATransition 时要添加包“QuartzCore.framework”,然后引进“#import <QuartzCore/QuartzCo ...

  8. jquery.validate.js 表单验证简单用法

    引入jquery.validate.js插件以及Jquery,在最后加上这个插件的方法名来引用.$('form').validate(); <!DOCTYPE html PUBLIC " ...

  9. NSCharacterSet 简单用法

    NSCharacterSet 简单用法 NSCharacterSet其实是许多字符或者数字或者符号的组合,在网络处理的时候会用到 NSMutableCharacterSet *base = [NSMu ...

随机推荐

  1. day74天中间件介绍

    一. importlib settings 执行结果: 两个process_request  process_response按照注册顺序的倒叙进行执行 PROCESS_VIEW  Process_v ...

  2. Mysql 练习题一

    库操作: 1. 创建 数据库  create database db1; 2. 使用数据库 use db1 3. 查看表  show tables; 4. 删除  drop database db1  ...

  3. 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 ...

  4. 二,PHP会话机制---session的基本使用

    1,思考:登录网站后,在每个网页都能拿到用户信息 (1) 使用超链接传递用户名,这样太繁琐了,不建议使用 . (2) 使用数据库,每打开一个页面都查询一次用户信息表,这样网页加载速度变慢,用户体验变差 ...

  5. 这里给大家介绍一下通过 Wi-Fi 连接“慷慨捐赠”你的身份信息的七种方法.

    这里给大家介绍一下通过 Wi-Fi 连接“慷慨捐赠”你的身份信息的七种方法和反制措施. 本文作者:黑子小盆友 1.利用免费热点 它们似乎无处不在,而且它们的数量会在接下来四年里增加三倍.但是它们当中很 ...

  6. iOS pods更新失败

    ――― TEMPLATE END ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― [!] Oh no, an erro ...

  7. iOS开发总结--三方平台开发之微信支付

    1.前言 现在很多应用都有支付功能,支付也是开发中比较麻烦的一个部分.其实,最麻烦的部分是商户帐号的审核,如果没有商户帐号,就没有你要给钱的那个对公账户. 2.关于交易 在这个金融类项目的开发中,接触 ...

  8. WebDriverAPI(7)

      查看页面元素的属性 测试网址 http://www.baidu.com Java语言版本API实例 @Test public void getWebElementAttribute() { dri ...

  9. openerp QWeb

    1.web 模块 注意,OpenERP 模块中 web 部分用到的所有文件必须被放置在模块内的 static 文件夹里.这是强制性的,出于安全考虑. 事实上,我们创建的文件夹 CSS,JS 和 XML ...

  10. (转)Mysql常用命令行

    原文:http://www.cnblogs.com/TsengYuen/archive/2012/01/11/2319034.html Mysql常用命令行 Mysql经常使用号令行大全 熬头招.my ...