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通用仓储类
前言 年底工作比较忙,年度总结还没写,项目要上线,回老家过年各种准备.尤其是给长辈给侄子侄女准备礼物头都大了. 原来想年前先出一版能用的,我看有点悬了,尽量先把大体功能弄出来,扔掉一些,保证能考试,然 ...
随机推荐
- 使用Session防止表单重复提交(不考虑多服务器)
在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 原理: 1, ...
- BZOJ1098 POI2007 办公楼biu 【链表+bfs】
Description FGD开办了一家电话公司.他雇用了N个职员,给了每个职员一部手机.每个职员的手机里都存储有一些同事的电话号码.由于FGD的公司规模不断扩大,旧的办公楼已经显得十分狭窄,FGD决 ...
- CALayer2-创建新的层
本文目录 一.添加一个简单的图层 二.添加一个显示图片的图层 三.为什么CALayer中使用CGColorRef和CGImageRef这2种数据类型,而不用UIColor和UIImage? 四.UIV ...
- python 中的异常处理
refer to: http://www.runoob.com/python/python-exceptions.html http://www.pythondoc.com/pythontutoria ...
- nginx 使用ctx实现数据共享,修改上下文
环境: init_worker_by_lua, set_by_lua, rewrite_by_lua, access_by_lua, content_by_lua, header_filter_by_ ...
- traits编程---萃取容器中迭代器的类型等
可以直接利用STL中定义好的traits_iterator来萃取 /*特性萃取器*/ template <class unknown_class> struct unknown_class ...
- strlen和sizeof的长度区别
strlen返回字符长度 而sizeof返回整个数组占多长,字符串的\0也会计入一个长度
- Vim自动补全插件----YouCompleteMe安装与配置
Vim自动补全插件----YouCompleteMe安装与配置 使用Vim编写程序少不了使用自动补全插件,在Linux下有没有类似VS中的Visual Assist X这么方便快捷的补全插件呢?以前用 ...
- java.lang.NoSuchFieldError: TRACE
Exception in thread "main" java.lang.NoSuchFieldError: TRACE at org.jboss.logging.Log4j ...
- 笔记:LNK2001不代表链接器真的需要链接相关符号
环境:VS2008 我们都知道,链接器在生成可执行程序时,会忽略那些没有用到的符号.但是昨天遇到一个链接问题,看起来与这条基本策略并不相符.首先看一个静态链接库的结构: lib | |---- ...