关系图

一、分层

二、DomainObjects构建edmx

三、EFRepositoryDemo.Domain定义仓储接口

 public interface IRepository<T>
where T : class
{
void Add(T entity);
void AddAll(IEnumerable<T> entities);
void Update(T entity);
void Update(IEnumerable<T> entities);
void Delete(T entity);
void Delete(Expression<Func<T, bool>> where);
void DeleteAll(IEnumerable<T> entities); void Clear();
T GetById(long Id);
T GetById(string Id);
T Get(Expression<Func<T, bool>> where);
IEnumerable<T> GetAll();
IEnumerable<T> GetMany(Expression<Func<T, bool>> where);
IEnumerable<T> GetAllLazy();
}

四、Infrastructure层 仓储的抽象基类(EF的CRUD)

Repository很明显的一个特征 是 内部没有SaveChanges()

 public abstract class EFRepositoryBase<T> where T : class
{
private Db1DbContext dataContext;
private readonly DbSet<T> dbset; protected IDatabaseFactory DatabaseFactory
{
get;
private set;
} protected Db1DbContext DataContext
{
get { return dataContext ?? (dataContext = DatabaseFactory.Get()); }
} protected EFRepositoryBase(IDatabaseFactory databaseFactory)
{
DatabaseFactory = databaseFactory;
dbset = DataContext.Set<T>();
} public virtual void Add(T entity)
{
dbset.Add(entity);
} //新增方法
public virtual void AddAll(IEnumerable<T> entities)
{
dbset.AddRange(entities);
} public virtual void Update(T entity)
{
dbset.Attach(entity);
dataContext.Entry(entity).State = EntityState.Modified;
} //新增方法
public virtual void Update(IEnumerable<T> entities)
{
foreach (T obj in entities)
{
dbset.Attach(obj);
dataContext.Entry(obj).State = EntityState.Modified;
}
} public virtual void Delete(T entity)
{
dbset.Remove(entity);
} public virtual void Delete(Expression<Func<T, bool>> where)
{
IEnumerable<T> objects = dbset.Where<T>(where).AsEnumerable();
dbset.RemoveRange(objects);
} //新增方法
public virtual void DeleteAll(IEnumerable<T> entities)
{
dbset.RemoveRange(entities);
} public virtual void Clear()
{
throw new NotImplementedException();
} public virtual T GetById(long id)
{
return dbset.Find(id);
} public virtual T GetById(string id)
{
return dbset.Find(id);
} public virtual IEnumerable<T> GetAll()
{
return dbset.ToList();
} public virtual IEnumerable<T> GetMany(Expression<Func<T, bool>> where)
{
return dbset.Where(where).ToList();
} public T Get(Expression<Func<T, bool>> where)
{
return dbset.Where(where).FirstOrDefault<T>();
} public virtual IEnumerable<T> GetAllLazy()
{
return dbset;
} }

五、Repository 

     public interface IStuEducationRepo : IRepository<TB_Stu_Education>
{ }
     public class StuEducationRepo : RepositoryBase<TB_Stu_Education>, IStuEducationRepo
{
public StuEducationRepo(IDatabaseFactory databaseFactory)
: base(databaseFactory)
{ } }

六、工作单元

在进行数据库的CUD操作时,因为Repository内部没有做SaveChanges()操作

所以要增加工作单元,进行包裹

     public interface IUnitOfWork
{
void Commit();
void CommitAsync();
}
 public class UnitOfWork : IUnitOfWork
{
private readonly IDatabaseFactory databaseFactory;
private Db1DbContext dataContext; public UnitOfWork(IDatabaseFactory databaseFactory)
{
this.databaseFactory = databaseFactory;
} protected Db1DbContext DataContext
{
get { return dataContext ?? (dataContext = databaseFactory.Get()); }
} public void Commit()
{
DataContext.SaveChanges();
} public void CommitAsync()
{
DataContext.SaveChangesAsync();
} }

七、Autofac注册

             var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); builder.RegisterType<DatabaseFactory>().As<IDatabaseFactory>().InstancePerLifetimeScope();
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerLifetimeScope(); builder.RegisterAssemblyTypes(typeof(StuEducationRepo).Assembly)
.Where(t => t.Name.EndsWith("Repo"))
.AsImplementedInterfaces().InstancePerLifetimeScope(); builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);
IContainer container = builder.Build();
var resolver = new AutofacWebApiDependencyResolver(container); // Configure Web API with the dependency resolver.
GlobalConfiguration.Configuration.DependencyResolver = resolver;

八、调用示例

 // GET api/<controller>/5
public string Get(int id)
{ var stuAccount = _stuAccountRepo.Get(p => p.UserId == );
if (stuAccount != null)
{
stuAccount.UserName = "张冬林Test";
} var stuEducation = _stuEducationRepo.GetMany(p => p.UserId == );
if (stuEducation != null && stuEducation.Count() > )
{
foreach (var i in stuEducation)
{
i.ModifyDate = new DateTime(, , );
}
} _unitOfWork.Commit(); return "value";
}

九、总结说明

  1、Global Autofac注册,以保证在一次Http请求的生命周期内的DbContext是单例的

        builder.RegisterType<DatabaseFactory>().As<IDatabaseFactory>().InstancePerLifetimeScope();
        private Db1DbContext dataContext;

        public Db1DbContext Get()
{
return dataContext ?? (dataContext = new Db1DbContext());
}

  这样Repository和UnitOfWork的DbContext 是一个对象,即同一个数据库上下文。所以 实现了 CRUD 与 数据持久化 两个步骤的分离

        public virtual void Update(T entity)
{
dbset.Attach(entity);
dataContext.Entry(entity).State = EntityState.Modified;
}
        private readonly IDatabaseFactory databaseFactory;
private Db1DbContext dataContext; public UnitOfWork(IDatabaseFactory databaseFactory)
{
this.databaseFactory = databaseFactory;
} protected Db1DbContext DataContext
{
get { return dataContext ?? (dataContext = databaseFactory.Get()); }
} public void Commit()
{
DataContext.SaveChanges();
}

 2、Entity Framework本身就是一仓储,但DDD的这种设计并非画蛇添足。接口定义与代码实现的分离,可以不用关心ORM,可以不用关心是何种DB

  附:源码下载

DDD-EF-数据仓储的更多相关文章

  1. 从零开始,搭建博客系统MVC5+EF6搭建框架(1),EF Code frist、实现泛型数据仓储以及业务逻辑

    前言      从上篇30岁找份程序员的工作(伪程序员的独白),文章开始,我说过我要用我自学的技术,来搭建一个博客系统,也希望大家给点意见,另外我很感谢博客园的各位朋友们,对我那篇算是自我阶段总结文章 ...

  2. 9.10 翻译系列:EF数据注解特性之StringLength【EF 6 Code-First系列】

    原文链接:https://www.entityframeworktutorial.net/code-first/stringlength-dataannotations-attribute-in-co ...

  3. 9.7 翻译系列:EF数据注解特性之--InverseProperty【EF 6 Code-First系列】

    原文链接:https://www.entityframeworktutorial.net/code-first/inverseproperty-dataannotations-attribute-in ...

  4. EF 数据查询效率对比

    优化的地方: 原地址:https://www.cnblogs.com/yaopengfei/p/9226328.html ①:如果仅是查询数据,并不对数据进行增.删.改操作,查询数据的时候可以取消状态 ...

  5. C#数据仓储类

    https://ninesky.codeplex.com/SourceControl/latest /*============================== 版本:v0.1 创建:2016.2 ...

  6. .netCoreMVC添加数据仓储

    在上一篇关于CodeFirst从零搭建ASP.NETCore2.0中搭建起了完整.netCoreMVC项目,在这一篇中将实现如何注册service服务和Repository数据仓储到web中实现数据的 ...

  7. Abp vNext 自定义 Ef Core 仓储引发异常

    问题 在使用自定义 Ef Core 仓储和 ABP vNext 注入的默认仓储时,通过两个 Repository 进行 Join 操作,提示 Cannot use multiple DbContext ...

  8. DDD与数据事务脚本

    DDD与数据事务脚本 扯淡 相信点进来看这篇文章的同学,大部分是因为标题里面的"DDD"所吸引!DDD并不是一个新技术,如果你百度一下它的历史就会知道,实际上它诞生于2004年, ...

  9. 【干货】利用MVC5+EF6搭建博客系统(一)EF Code frist、实现泛型数据仓储以及业务逻辑

    习MVC有一段时间了,决定自己写一套Demo了,写完源码再共享. PS:如果图片模糊,鼠标右击复制图片网址,然后在浏览器中打开即可. 一.框架搭建 二.创建数据库 1.创建一个空的EF code fr ...

  10. 用MVC5+EF6+WebApi 做一个考试功能(六) 仓储模式 打造EF通用仓储类

    前言 年底工作比较忙,年度总结还没写,项目要上线,回老家过年各种准备.尤其是给长辈给侄子侄女准备礼物头都大了. 原来想年前先出一版能用的,我看有点悬了,尽量先把大体功能弄出来,扔掉一些,保证能考试,然 ...

随机推荐

  1. bzoj 4303 数列

    bzoj 4303 数列 二维 \(KD-Tree\) 模板题. \(KD-Tree\) 虽然在更新和查询的方式上类似于线段树,但其本身定义是类似于用 \(splay/fhq\ treap\) 维护区 ...

  2. 使 32 位程序使用大于 2GB 的内存

    不管在 32 位 Windows 上还是在 64 位 Windows 上,32 位的应用程序都只能使用最大 2GB 的内存,这是我们司空见惯的一个设定.但其实 Windows 提供了一些方法让我们打破 ...

  3. callback回调函数-python

    链接:http://www.zhihu.com/question/19801131/answer/27459821来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 编程分 ...

  4. Tornador之初识(一)

    一.最简单的web服务器 import socket def handle_request(client): buf = client.recv(1024) client.send("HTT ...

  5. MTK-shot mode

    enum EShotMode{    eShotMode_NormalShot,                           /*!< Normal Shot */    eShotMo ...

  6. RBAC (基于角色的访问控制)

    基于角色的访问控制(Role-Based Access Control)作为传统访问控制(自主访问,强制访问)的有前景的代替受到广泛的关注.在RBAC中,权限与角色相关联,用户通过成为适当角色的成员而 ...

  7. oracle11g卸载(win10)

    oracle11g卸载(win10) 0.已在win10安装oracle11g 1.开始->设置->控制面板->管理工具->服务 停止所有Oracle服务. 2.运行Unive ...

  8. L2TP/IPSec一键安装脚本

    本脚本适用环境:系统支持:CentOS6+,Debian7+,Ubuntu12+内存要求:≥128M更新日期:2017 年 05 月 28 日 关于本脚本:名词解释如下L2TP(Layer 2 Tun ...

  9. 在 FastAdmin 中启动 ThinkPHP 5 的请求缓存分析

    在 FastAdmin 中启动 ThinkPHP 5 的请求缓存分析 缓存的基础配置 ThinkPHP 5 中有一个请求缓存:1 'request_cache' => true, 'reques ...

  10. RK3288 OTG切换为Host模式

    OTG = On The Go,是USB的一种工作模式 USB协议中规定了两类设备,一类是Host.一类是Device. Host为主控设备,如PC,Device为从设备,如鼠标.U盘等,Device ...