其实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. efcore操作mysql,出现System.InvalidOperationException:“No coercion operator is defined between types 'System.Int16' and 'System.Boolean'.”

    这个恶心的问题,只需要把EF的依赖换成 Pomelo.EntityFrameworkCore.MySql 库即可解决

  2. 初识GitHub与Git

    在初次接触GitHub的时候,英语渣渣本渣真是深感无奈啊..... ORZ 在好友的帮助下,也算是初步入门了吧. 谨以此文作为初级使用手册记录,希望能帮助到你. 一.首先要申请一个GitHub账户 二 ...

  3. 全球第一开源云ERP Odoo操作手册 模块安装和界面汉化指南

    之前介绍了odoo的安装和初始设置以及数据库,下面来介绍odoo的模块安装和界面汉化. 1.4 模块安装和界面汉化 Odoo 的功能包含在不同的模块中, 刚创建的数据库除 Odoo 的核心模块外, 其 ...

  4. hashlib 和loggin模块

    1.摘要算法hashlib 1. md5加密 #1. 摘要算法 #md5加密算法 32位 import hashlib username ="alex" md5_obj =hash ...

  5. GCC升级问题解决:configure: error: Building GCC requires GMP 4.2+, MPFR 2.4.0+ and MPC 0.8.0+.,mpfr2.4.0

    如果遇到类似问题: configure: error: Building GCC requires GMP 4.2+, MPFR 2.4.0+ and MPC 0.8.0+.,mpfr2.4.0 解决 ...

  6. jenkins 配置。

    为了避免在jenkins操作过程中的权限问题. 将安装在/Users/Shared/jenkins目录下的卸载. sudo launchctl unload /Library/LaunchDaemon ...

  7. 【xsy1058】 单词 乱搞

    题目大意:给你$n$个长度为$m$的字符串,字符集仅为{x,y,z}三个字符,定义两个字符串$(s_i,s_j)$的相似度为$\sum_{k=1}^{m} [s_i[k]==s_j[k]]$. 从$0 ...

  8. 简单选择排序实现(Java)

    简单选择排序实现 简单选择排序就是通过n-i次关键字之间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i (1 ≤ i ≤ n)个记录交换. 代码实现: public class Selec ...

  9. TestNG参数

    dependsOnMethods可以使测试用例按某个特定的顺序执行 实例: @Test(dependsOnMethods=“s”) public  void  a() System.out.print ...

  10. Ubuntu16.04 Nvidia驱动、CUDA安装

    安装Nvidia驱动和CUDA时往往很费力,经常有莫名奇妙的错误,这次安装十分顺畅,权当记录一下,以方便以后再次安装. 一.Nvidia显卡驱动安装 sudo add-apt-repository p ...