实现有界上下文到基于实体框架的基础设施

bah*_*lan 8 domain-driven-design unit-of-work repository-pattern bounded-contexts entity-framework-5

我创建了一个基础设施,这是我们新的内部网络项目,并试图遵循几乎所有最佳实践.另外,我想提一下,这是我第一次从零创建架构.

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

我试着解释下面的现状.

DbCore:负责数据操作.实体框架5代码首先使用.只有一个DbContext类,并且在其中定义了所有DbSet.另外,GenericRepository模式和Unit of Work模式基于以下接口实现.

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);
    }
Run Code Online (Sandbox Code Playgroud)

IUnitOfWork

 public interface IUnitOfWork {
        void Dispose();
        IGenericRepository<Test> TestRepository {
            get;
        }
        IGenericRepository<Log> LogRepository {
            get;
        }
        void Save();
    }
Run Code Online (Sandbox Code Playgroud)

模型: DbCore和实体框架域的负责存储实体模型 :表示业务逻辑层还存储存储在Models项目中的实体对象的DTO.当前存储在Service类中的业务逻辑实现了以下接口 IService

public interface IService<TEntity> {

        IEnumerable<TEntity> Get();
        TEntity GetByID(int id);
        void Insert(TEntity entity);
    }
Run Code Online (Sandbox Code Playgroud)

此服务类通过ctor参数获取UnitOfWork并用于操作.Automapper也实现了将实体对象转换为DTO,反之亦然.从现在开始,所有上层不再对实体模型感兴趣,只使用DTO.所以几乎所有项目(包括api和web)都引用了这个项目.

常见:负责存储常用的库,如日志记录.

WebCore:负责为基于Web的项目(如API或MVC)存储常用库.还包含基于MVC的项目的扩展,处理程序和过滤器.

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

Web:基于ASP.Net MVC 4的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);
    }
Run Code Online (Sandbox Code Playgroud)

Autofac适用于所有项目的IoC和DI.

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

现在我想弄清楚以下事情,

问题1:我使用的方式是否有任何不可能被强制执行?

问题2:实施有界上下文的最佳方法是什么?我最近观看了Julie Lerman的视频并审阅了大量示例项目.我看到从DbContext派生BC的常见事物.但我无法确定.因为我以为BC应该在域(业务逻辑)层而不是在DbCore(数据访问)层.

问题3:正如我上面提到的,我的Api和Web项目使用DTO,因此它们都需要引用域层.但我不喜欢它,因为我正在使用API​​从UI中分离业务层,并再次为实体耦合它们.但我找不到比这更好的方法.

这成了一个很长的问题,但如果你与我分享你的想法以创造更好的架构,我将非常高兴.

Pau*_*ner 30

问题1:假设您拥有复杂的业务领域和重要的业务逻辑,因此您必须将域层与基础架构问题隔离开来,这是值得的.但是,情况往往并非如此.如果您主要只是将数据从数据库移动到UI并再次返回,那么这就是过度工程,您应该寻找具有较少移动部件的东西.

问题2:您有多少个不同的域模型(使用不同的普遍存在的语言)?一?二?三?对于每种型号,尽可能将其与其他型号和基础设施问题隔离开来.

Eric Evans将有界语境定义为语言边界(引自他的书):

有界背景界定了特定模型的适用性,以便团队成员对必须一致的内容以及与其他上下文的关系有清晰和共同的理解.在该CONTEXT中,努力使模型在逻辑上统一,但不要担心超出这些范围的适用性.在其他背景中,其他模型适用于术语,概念和规则以及UBIQUITOUS LANGUAGE方言的差异.

DBContext可能指向正确的方向,但请记住它是基础结构工件,而不是域概念.它"代表了工作单元和存储库模式的组合,使您能够查询数据库并将更改组合在一起,然后将这些更改作为一个单元写回到商店."_(来自MSDN Docs).

DDD是关于域建模的:使用模型来解决复杂业务领域中的硬业务问题.从技术考虑中获得模型边界可以感觉像尾巴摇摆着狗.从概念上定义模型的边界,然后相应地调整您的技术基础架构.

问题3: DTO可以是强制执行上下文边界的好方法,例如API.然后,API可以作为其他模型的反腐败层.人们通常将它们用于UI的原因是避免将UI概念渗透到域模型中.

不要寻求完美的建筑.并且意识到"最佳实践"实际上只是基于特定情况的指南.遵循其他更有经验的人制定的指导原则,并了解您的情况可能略有不同.当您发现摩擦时,请使用您对重构设计决策的期望.例如,如果稍后您发现UI的DTO过度,则删除它们.随时随地简化.

  • 希望能够在这里点击+1几百次! (8认同)