Domain driven design 实现基于框架的有界上下文到实体的基础架构

Domain driven design 实现基于框架的有界上下文到实体的基础架构,domain-driven-design,repository-pattern,entity-framework-5,unit-of-work,bounded-contexts,Domain Driven Design,Repository Pattern,Entity Framework 5,Unit Of Work,Bounded Contexts,我创建了一个基础设施,这是我们全新的内部网项目,并尝试遵循几乎所有的最佳实践。我还想提到,这是我第一次从零开始创建架构 目前,我的基础架构的第一个版本已经准备就绪,并且运行良好。但我想在下一个版本中实现有界上下文结构 我试图解释一下目前的情况 DbCore:负责数据操作。首先使用的是实体框架5代码。只有一个DbContext类和其中定义的所有数据库集。还基于以下接口实现了GenericRepository模式和工作单元模式 IGenericRepository public interface

我创建了一个基础设施,这是我们全新的内部网项目,并尝试遵循几乎所有的最佳实践。我还想提到,这是我第一次从零开始创建架构

目前,我的基础架构的第一个版本已经准备就绪,并且运行良好。但我想在下一个版本中实现有界上下文结构

我试图解释一下目前的情况

DbCore:负责数据操作。首先使用的是实体框架5代码。只有一个DbContext类和其中定义的所有数据库集。还基于以下接口实现了GenericRepository模式和工作单元模式

IGenericRepository

public interface IGenericRepository<TEntity>
     where TEntity : class {
        void Delete(object id);
        void Delete(TEntity entityToDelete);
        System.Collections.Generic.IEnumerable<TEntity> Get(System.Linq.Expressions.Expression<Func<TEntity, bool>> filter = null, Func<System.Linq.IQueryable<TEntity>, System.Linq.IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "");
        System.Collections.Generic.IEnumerable<TEntity> GetAll();
        TEntity GetByID(object id);
        System.Collections.Generic.IEnumerable<TEntity> GetWithRawSql(string query, params object[] parameters);
        void Insert(TEntity entity);
        void Update(TEntity entityToUpdate);
    }
公共接口IGenericRepository
地点:班级{
作废删除(对象id);
无效删除(TEntity entityToDelete);
System.Collections.Generic.IEnumerable Get(System.Linq.Expressions.Expression filter=null,Func orderBy=null,string includeProperties=“”);
System.Collections.Generic.IEnumerable GetAll();
TEntity GetByID(对象id);
System.Collections.Generic.IEnumerable GetWithRawSql(字符串查询,参数对象[]参数);
无效插入(TEntity实体);
无效更新(TEntity entityToUpdate);
}
i工作单元

 public interface IUnitOfWork {
        void Dispose();
        IGenericRepository<Test> TestRepository {
            get;
        }
        IGenericRepository<Log> LogRepository {
            get;
        }
        void Save();
    }
公共接口IUnitOfWork{
无效处置();
IGenericRepository测试库{
得到;
}
IGenericRepository日志存储库{
得到;
}
作废保存();
}
模型:负责存储DbCore和实体框架的实体模型 域:表示业务逻辑层还存储存储在模型项目中的实体对象的DTO。当前业务逻辑存储在实现以下接口的服务类中 iSeries设备

public interface IService<TEntity> {

        IEnumerable<TEntity> Get();
        TEntity GetByID(int id);
        void Insert(TEntity entity);
    }
公共接口iSeries设备{
IEnumerable Get();
TEntity GetByID(intid);
无效插入(TEntity实体);
}
此服务类通过ctor参数获取UnitOfWork并用于操作。还实现了Automapper,以将实体对象转换为DTO,或将实体对象转换为DTO。 从现在起,所有上层不再对实体模型感兴趣,只使用DTO。所以几乎所有的项目(包括api和web)都引用这个项目

Common:负责存储日志等常用库

WebCore:负责存储API或MVC等基于web的项目的常用库。还包含用于基于MVC的项目的扩展、处理程序和过滤器

Api:ASP.Net MVC Web Api项目代表服务层。使用域层并服务于客户端。 控制器获取IService接口作为ctor参数,并使用它通过域层访问数据层

Web:ASP.Net基于mvc4的Web项目,负责与用户交互。使用Api方法访问数据。所有控制器都获得一个名为IConsumeRepository的接口,该接口通过HttpClient连接API

 public interface IConsumeRepository<TEntity> {
        Task<TEntity> Create(TEntity TestInfo);
        Task Delete(int id);       
        Task<IEnumerable<TEntity>> Get();
        Task<TEntity> Get(int id);
        TEntity New();       
        Task<TEntity> Update(TEntity TestInfo, int entityId);
    }
公共接口IConsumeRepository{
任务创建(TEntity TestInfo);
任务删除(int-id);
任务Get();
任务获取(int-id);
TEntity New();
任务更新(TEntity TestInfo,int entityId);
}
Autofac负责所有项目的IoC和DI

现在这是我目前的基础设施,我想我已经解释了所有需要评估的内容

现在我想弄清楚下面的事情

问题1:有什么东西不能像我以前那样推动吗

问题2:实现有界上下文的最佳方法是什么?我最近看了朱莉·勒曼的视频,并回顾了许多样本项目。从DbContext派生BC是我看到的一个常见现象。但我不能确定。因为我认为BC应该在域(业务逻辑)层,而不是DbCore(数据访问)层

问题3:如上所述,我的Api和Web项目使用DTO,因此它们都需要有域层引用。但我不喜欢它,因为我用API将业务层和UI分离,并为实体再次耦合它们。但我找不到比这更好的办法了


这是一个很长的问题,但如果您能与我分享您的想法,以创建更好的体系结构,我将非常高兴。

问题1:假设您有一个复杂的业务领域和重要的业务逻辑,那么您可以做出努力,因为您必须将域层与基础架构问题隔离开来。然而,情况往往并非如此。如果您主要只是将数据从数据库移动到UI,然后再移动回来,那么这是过度工程化的,您应该寻找移动部分较少的数据

问题2:您有多少不同的领域模型(使用不同的通用语言)?一个?两个?三个?对于每个模型,尽可能将其与其他模型和基础架构问题隔离开来

埃里克·埃文斯(Eric Evans)将有界语境主要定义为语言边界(引自他的书):

有界上下文界定了特定模型的适用性 团队成员对发生的事情有一个清晰和共同的理解 保持一致,以及它与其他上下文的关系。在此范围内 上下文,努力保持模型在逻辑上的统一,但不要担心 关于那些界限之外的适用性。在其他情况下,其他 模型适用于不同的术语、概念和规则, 和无处不在的语言的方言

DBContext可能为您指明了正确的方向,但请记住,它是一个基础架构工件,而不是一个域概念。它“表示工作单元和存储库的组合