我的问题与此类似:Repository pattern and mapping between domain models and Entity Framework。
我在这里做了很多关于以下内容的阅读:
1)将ORM直接映射到域模型
2)将ORM映射到数据模型,然后将数据模型映射到域模型(反之亦然)
我理解这两种方法的好处和局限。我也理解一种方法比另一方更受青睐的情景。
网上有很多例子,展示了如何做选项1.但是,我找不到任何示例代码,它显示了如何做选项2.我在这里阅读关于选项二的问题,如第一个引用的那个这篇文章的一行,即问题是关于选项二,但答案是关于选项一 - 而且有评论指出选项二可能更合适。
因此,我的问题是关于如何从映射和验证角度做选项一:
映射
我相信在将域模型映射到数据模型时我可以这样做:
public PersonDomain GetById(Guid id)
{
return AutoMapper.Mapper.Map<PersonDomain>(Session.Get<PersonData>(id));
}
我相信在将数据模型映射到存储库中的域模型时(保护不变量),我已经这样做了:
protected PersonDomain ToPersonDomain(PersonData personData)
{
return new PersonDomain(personData.ID, personData.Name, personData.DateOfBirth);
}
验证
我想在PersonDomain类中执行此操作:
public class PersonDomain
{
public Guid ID{ get; private set; }
public DateTime DateOfBirth { get; private set; }
public string Name { get; private set; }
public PersonDomain(Guid id, DateTime dateOfBirth, string name)
{
if (id == Guid.Empty())
throw new ArguementException("Guid cannot be empty");
if (name =="")
throw new ArguementException("Name cannot be empty");
ID=id;
Name=NAME;
DateOfBirth=dateOfBirth;
}
}
然而,我发现的每个例子都告诉我不要在构造函数中加入验证。我的一个想法是避免原始的痴迷如下:
public class PersonDomain
{
public ID ID{ get; private set; }
public DateOfBirth DateOfBirth { get; private set; }
public Name Name { get; private set; }
public PersonDomain(ID id, DateOfBirth dateOfBirth, Name name)
{
if (id == null)
throw new ArguementNullException("ID cannot be null");
if (name ==null)
throw new ArguementNullException("Name cannot be null");
ID=id;
Name=name;
DateOfBirth=dateOfBirth;
}
}
然而,在这种情况下;仍然在构造函数中进行验证。
问题
我的两个问题是:
1)我是否正确理解了域模型和数据模型之间的映射(反之亦然),还是有更优雅的方法来处理这种情况(数据模型和域模型之间的映射,反之亦然)?
2)在这种情况下,我应该在PersonDomain实体的构造函数中放置任何验证逻辑吗?
更新27/02/18
此链接对我最有帮助:http://www.dataworks.ie/Blog/Item/entity_framework_5_with_automapper_and_repository_pattern
答案 0 :(得分:4)
我发现的每个例子都告诉我不要在构造函数中放置验证。
我认为你需要找到更多的例子。
考虑在更深层次上发生的事情可能会有所帮助。从根本上说,我们要做的是确保precondition成立。一种方法是验证“无处不在”的前提条件;但是DRY principle表明我们更愿意在阻塞点捕获前置条件,并确保所有需要该前置条件的代码路径必须通过该阻塞点。
在Java(DDD开始的地方)和C#中,我们可以让类型系统做很多繁重的工作;类型系统强制保证任何类型的使用都经过构造函数,所以如果我们在构造函数中建立前置条件,我们就可以了。
这里的关键思想不是“构造函数”,而是“阻塞点”;使用named constructor或工厂也可以提供服务。
如果您的映射代码路径通过阻塞点,那就很好。
如果没有...,则会失去类型检查所提供的优势。
一个可能的答案是让您的域模型更加明确;并承认存在未经验证的域概念表示,以后可以明确验证。
如果您眯着眼睛,您可能会认识到这是处理来自不受信任来源的输入的一种方式。我们明确地为不受信任的数据建模,让我们的映射代码为我们生成它,然后在域模型中我们安排不受信任的数据通过阻塞点,然后对已经过消毒的变体进行处理
Domain Modeling Made Functional很好地涵盖了这个想法;您可以通过观看Scott Wlaschin的演讲Domain Driven Design with the F# type System
来预览主要主题答案 1 :(得分:0)
1)我是否理解了域模型和数据之间的映射 模型(反之亦然)正确或有更优雅的方式 接近这个(数据模型和域模型之间的映射) 反之亦然)?
我会说ORM应该将域模型(实体)映射到数据库,而您将使用数据模型将数据表示到外部世界(UI) ,REST ......)。
2)我应该在构造函数中放置任何验证逻辑吗? 在这种情况下,PersonDomain实体?
将域验证逻辑放入域对象构造函数中是可以的。但是如果你想进行特定于UI的验证,它应该可以在映射到数据模型的一些验证类中完成,这样你就可以向用户返回一个很好的错误。