其实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. CentOS ASP.NET Core Runtime Jexus跨平台布署

    .net core 开源和跨平台,能布署到当前主流的Windows,Linux,macOS 系统上.本篇我们将在 Linux 系统上使用 ASP.NET Core Runtime 和 Jexus 布署 ...

  2. NetCore偶尔有用篇:NetCore项目添加MIME

    一.简介 1.系统默认给我们提供的一些文件类型的处理方式. 2.系统没有为我们提供处理的文件类型无法使用,例如:apk 3.这里候就需要自己添加MIME,才能进行访问 4.下面就是添加apk访问的示例 ...

  3. CSS精灵技术

    在CSDN中浏览博客时,在博客的结束有上一篇和下一篇的按钮,当我们把鼠标放上去的时候,可以看到这两个按钮会进行颜色的改变,这种技术称为CSS精灵技术.通过查看源发现,其实他是通过超级链接的伪类实现的, ...

  4. MVVM Light 新手入门(2) :ViewModel / Model 中定义“属性” ,并在View中调用

    今天学习MVVM架构中“属性”的添加并调用,特记录如下,学习资料均来自于网络,特别感谢翁智华的利刃 MVVMLight系列. 一个窗口的基本模型如下: View(视图) -> ViewModel ...

  5. UE4随笔(一)准备过程

    19号,也就是中国时间20日凌晨,虚幻4放出了"订阅制"这个重磅炸弹,估计出乎大多数人的想象,已经不止一个同事表示"自己的引擎这下没用了". 笔者前天搞定了付款 ...

  6. python 模块导入全局变量

    在哪种情况下需要从模块导入全局变量 项目里多个脚本均更改「某一个全局变量」时 全量变量需要实现可配置时 从模块导入全局变量的方法 from test_prokject import global_va ...

  7. 【mongodb】——常用命令大全

    MongoDB是NoSQL数据库系统中比较流行的数据库之一.它也是最接近关系型数据库的,一个数据库可以包含多个集合(Collection),类似于关系数据库中的表:而每个集合中可以存储一组由列标识的记 ...

  8. this引用逃逸(使用内部类获取未外部类未初始化完的变量),多态父类使用子类未初始化完的变量

    1,this引用逃逸 并发编程实践中,this引用逃逸("this"escape)是指对象还没有构造完成,它的this引用就被发布出去了. 这是危及到线程安全的,因为其他线程有可能 ...

  9. day 42 mysql 数据库(2)

    前情提要: 本节继续学习数据库   一:ddl 创建表 >字段名 >数据类型 >约束规则 >显示建表语句 修改表: 二:数据类型 >数值类型 >小数类型 >字 ...

  10. 语义分割Semantic Segmentation研究综述

    语义分割和实例分割概念 语义分割:对图像中的每个像素都划分出对应的类别,实现像素级别的分类. 实例分割:目标是进行像素级别的分类,而且在具体类别的基础上区别不同的实例. 语义分割(Semantic S ...