8

我已经创建了一个基础设施,我们的品牌新的Intranet项目,并试图遵循几乎所有的最佳实践。另外我也想提一下,这是我第一次从零创建架构。为基于实体框架的基础设施实施有界的上下文

目前我的基础架构的第一个版本已经准备就绪并且工作正常。但是我想在下一个版本中实现有界的上下文结构。

我试图解释下面的现状。

DbCore:负责数据操作。实体框架5代码首次使用。只有一个DbContext类和其中定义的所有DbSets。此外,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); 
    } 

IUnitOfWork

public interface IUnitOfWork { 
     void Dispose(); 
     IGenericRepository<Test> TestRepository { 
      get; 
     } 
     IGenericRepository<Log> LogRepository { 
      get; 
     } 
     void Save(); 
    } 

型号:用于DbCore和Entity Framework负责存储实体模型 域:表示业务逻辑层还存储的DTO的实体存储在Models项目中的对象。目前业务逻辑存储在服务类中实现的界面如下 IService

public interface IService<TEntity> { 

     IEnumerable<TEntity> Get(); 
     TEntity GetByID(int id); 
     void Insert(TEntity entity); 
    } 

这个服务类构造函数通过参数得到的UnitOfWork和使用操作。此外Automapper实现将实体对象转换为DTO或反之亦然。 从现在起,所有上层不再对实体模型感兴趣,只使用DTO。所以几乎所有的项目(包括api和web)都引用这个项目。

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

WebCore:负责存储API或MVC等基于web的项目的常用库。还包含基于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); 
    } 

Autofac负责所有项目的IoC和DI。

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

现在,我试图找出以下的事情,

问题1:有什么事情一定不能impelemented我使用的方法是什么?

问题2:实现有界上下文的最佳方法是什么?我最近观看了Julie Lerman的视频并回顾了很多示例项目。常见的事情,我看到从DbContext派生BC。但我无法确定。因为我曾经认为BC应该位于域(业务逻辑)层而不是DbCore(数据访问)层。

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

这成了一个很长的问题,但如果您与我分享您的想法以创建更好的建筑,我将非常高兴。

回答

30

问题1:假设您有一个复杂的业务领域和重要的业务逻辑,可能值得付出努力,因为您必须将您的域层与基础架构问题隔离开来。但是,情况往往不是这样。如果您主要只是将数据从数据库移动到UI并返回,那么这就是过度工程,您应该使用更少的移动部件来寻找。

问题2:您有多少个不同的域模型(使用不同的泛在语言)?一?二?三?对于每个模型,尽可能将其与其他模型和基础设施问题分开。

Eric Evans的定义界上下文,主要用作语言边界(引自他的书):

一个限界上下文限定了特定模型的适用性所以 团队成员有一个明确的并共同理解 的一致性以及它与其他上下文的关系。在该范围内,努力保持模型在逻辑上统一,但不要担心 关于在这些范围之外的适用性。在其他上下文中,其他 模型适用,术语不同,概念和规则, 和通用语言的方言。

的DbContext可能指向你在正确的方向,但请记住它是一个基础设施神器,域的概念。它“代表工作单元和存储库模式的组合,使您能够查询数据库并将所做的更改分组在一起,然后将其作为一个单元写回商店。”_(来自MSDN Docs)。

DDD是关于领域建模:使用模型解决复杂业务领域的难题。从技术考虑中推导模型边界可以感觉到尾巴摇摆狗。从概念上定义模型的边界,然后相应地调整技术基础架构。

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

不要寻求一个完美的建筑。并意识到“最佳实践”实际上只是基于特定情况的指导方针。遵循其他更有经验的人所制定的指导方针,并了解到您的情况可能有微妙的差异。当你发现摩擦时,使用你所期望的重构设计决策的期望。例如,如果稍后您发现到用户界面的DTO过量,则将其删除。尽可能简化。

+8

想要在这里点击+1几百次! – 2013-02-15 14:32:35