DDD-EF-数据仓储
关系图

一、分层

二、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-数据仓储的更多相关文章
- 从零开始,搭建博客系统MVC5+EF6搭建框架(1),EF Code frist、实现泛型数据仓储以及业务逻辑
前言 从上篇30岁找份程序员的工作(伪程序员的独白),文章开始,我说过我要用我自学的技术,来搭建一个博客系统,也希望大家给点意见,另外我很感谢博客园的各位朋友们,对我那篇算是自我阶段总结文章 ...
- 9.10 翻译系列:EF数据注解特性之StringLength【EF 6 Code-First系列】
原文链接:https://www.entityframeworktutorial.net/code-first/stringlength-dataannotations-attribute-in-co ...
- 9.7 翻译系列:EF数据注解特性之--InverseProperty【EF 6 Code-First系列】
原文链接:https://www.entityframeworktutorial.net/code-first/inverseproperty-dataannotations-attribute-in ...
- EF 数据查询效率对比
优化的地方: 原地址:https://www.cnblogs.com/yaopengfei/p/9226328.html ①:如果仅是查询数据,并不对数据进行增.删.改操作,查询数据的时候可以取消状态 ...
- C#数据仓储类
https://ninesky.codeplex.com/SourceControl/latest /*============================== 版本:v0.1 创建:2016.2 ...
- .netCoreMVC添加数据仓储
在上一篇关于CodeFirst从零搭建ASP.NETCore2.0中搭建起了完整.netCoreMVC项目,在这一篇中将实现如何注册service服务和Repository数据仓储到web中实现数据的 ...
- Abp vNext 自定义 Ef Core 仓储引发异常
问题 在使用自定义 Ef Core 仓储和 ABP vNext 注入的默认仓储时,通过两个 Repository 进行 Join 操作,提示 Cannot use multiple DbContext ...
- DDD与数据事务脚本
DDD与数据事务脚本 扯淡 相信点进来看这篇文章的同学,大部分是因为标题里面的"DDD"所吸引!DDD并不是一个新技术,如果你百度一下它的历史就会知道,实际上它诞生于2004年, ...
- 【干货】利用MVC5+EF6搭建博客系统(一)EF Code frist、实现泛型数据仓储以及业务逻辑
习MVC有一段时间了,决定自己写一套Demo了,写完源码再共享. PS:如果图片模糊,鼠标右击复制图片网址,然后在浏览器中打开即可. 一.框架搭建 二.创建数据库 1.创建一个空的EF code fr ...
- 用MVC5+EF6+WebApi 做一个考试功能(六) 仓储模式 打造EF通用仓储类
前言 年底工作比较忙,年度总结还没写,项目要上线,回老家过年各种准备.尤其是给长辈给侄子侄女准备礼物头都大了. 原来想年前先出一版能用的,我看有点悬了,尽量先把大体功能弄出来,扔掉一些,保证能考试,然 ...
随机推荐
- idea Java spring 入门 demo
根据这个 来实现 理解 https://www.cnblogs.com/xing901022/p/3963962.html 这里没有说如何导入包,现在我们用 idea 来实现 新建项目结构后 RUN ...
- Mac OS X系统 HomeBrew的安装和简单使用
1. 前言 作为linux系统的忠实粉丝,我们都很喜欢 (Debian/Ubuntu)系列的apt包管理系统和(Redhat/Fedora)系列的yum包管理系统. 包括Windows用户都有多种方便 ...
- 实用且堪称神器的Chrome插件推荐
前言 相信很多人都在使用 Chrome 浏览器,其流畅的浏览体验得到了不少用户的偏爱,但流畅只是一方面, Chrome 最大的优势还是其支持众多强大好用的扩展程序(Extensions).最近为了更好 ...
- thinkphp 使每一个模板页都包括一个header文件和一个footer文件
在开发的过程中,常常遇到要使每一个模板页都包括一个header文件和一个footer文件.thinkPHP的模板布局为我们提供了一个叫全局配置方式可以解决问题. 1. 在配置文件里开启LAYOUT_O ...
- Unit07: MyBatis框架简介 、 MyBatis基本应用
Unit07: MyBatis框架简介 . MyBatis基本应用 1. myBatis (1)myBatis是什么? 是一个开源的持久层框架. 注:myBatis底层仍然是jdbc. (2)编程步骤 ...
- 数据结构与算法JavaScript描述——列表
1.列表的抽象数据类型定义 2.实现列表类: 2.1 append:给列表添加元素: 2.2 remove: 从列表中删除元素: 2.3 find方法: 2.4 length:列表中有多少个元素: ...
- mac下的安装神奇 brew --例子 安装 mysql
da打开终端 输入bre 输入 bre search mysql (查找mysql版本) 输入 bre install mysql@5.6(选择mysql版本安装)
- PAT 甲级 1007 Maximum Subsequence Sum (25)(25 分)(0不是负数,水题)
1007 Maximum Subsequence Sum (25)(25 分) Given a sequence of K integers { N~1~, N~2~, ..., N~K~ }. A ...
- python学习(二十三) String(下) 分片和索引
分片: 记住, 是开闭区间. a = "abcdef"print(a[:])print(a[1:])print(a[:3])print(a[-2])print(a[:-2])pri ...
- HTTP请求与响应协议
HTTP(hypertext transport protocol),即超文本传输协议.这个协议详细规定了浏览器和万维网服务器之间互相通信的规则 HTTP就是一个通信规则,通信规则规定了客户端发送给服 ...