c# - 具有行为和 ORM 的丰富域模型

标签 c# .net architecture orm domain-driven-design

在观看了 Jimmy Bogard (http://ndcoslo.oktaset.com/Agenda) 的 NDC12 演讲“制作邪恶的领域模型”之后,我在徘徊如何保持这种领域模型。
这是演示文稿中的示例类:

public class Member
{
    List<Offer> _offers;

    public Member(string firstName, string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
        _offers = new List<Offer>();
    }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public IEnumerable<Offer> AssignedOffers { 
        get { return _offers; }
    }

    public int NumberOfOffers { get; private set; }

    public Offer AssignOffer(OfferType offerType, IOfferValueCalc valueCalc)
    {
        var value = valueCalc.CalculateValue(this, offerType);
        var expiration = offerType.CalculateExpiration();
        var offer = new Offer(this, offerType, expiration, value);
        _offers.Add(offer);
        NumberOfOffers++;
        return offer;
    }
}

所以这个领域模型中包含了一些规则:
- 成员(member)必须有名字和姓氏
- 无法在外部更改优惠数量
- 成员(member)负责创建新报价,计算其值(value)和分配

如果尝试将其映射到 Entity Framework 或 NHibernate 等 ORM,它将无法工作。 那么,使用 ORM 将这种模型映射到数据库的最佳方法是什么?
例如,如果没有 setter,我如何从数据库加载 AssignedOffers?

唯一对我来说有意义的是使用命令/查询架构:查询总是使用 DTO 作为结果,而不是域实体,并且命令是在域模型上完成的。此外,事件溯源非常适合域模型上的行为。但这种 CQS 架构可能并不适合所有项目,尤其是 brownfield。还是不行?

我知道这里有类似的问题,但找不到具体的例子和解决方案。

最佳答案

这其实是个很好的问题,也是我思考过的问题。创建完全封装的适当域对象(即没有属性 setter )并使用 ORM 直接构建域对象可能很困难。

根据我的经验,有 3 种方法可以解决这个问题:

  • 正如 Luka 已经提到的,NHibernate 支持映射到私有(private)字段,而不是属性 setter 。
  • 如果使用 EF(我认为它不支持上述功能),您可以使用 memento pattern将状态恢复到您的域对象。例如您使用 Entity Framework 来填充您的域实体接受的“纪念品”对象以设置其私有(private)字段。
  • 正如您所指出的,将 CQRS 与事件溯源结合使用可以消除此问题。这是我制作完美封装域对象的首选方法,它还具有事件溯源的所有附加优势。

关于c# - 具有行为和 ORM 的丰富域模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11222720/

相关文章:

c# - 将 MimeKit 消息作为文件返回给浏览器

c# - 如何访问DataRow的内容?

java - 寻求建议: overview/detail representation of models

java - 服务层和 Controller : who takes care of what?

用于翻阅基于 JPane 的 View 的 Java Swing 架构

c# - 在 MonoDevelop 中,如何将应用程序输出设置为固定宽度字体?

c# - Entity Framework 日期组合查询

.net - MSBuild 错误 : The attribute "Remove" in element <ProjectReference> is unrecognized

javascript - 通过 Grunt 任务注入(inject)内容,具体取决于 ASP.NET 项目构建配置

.net - 用于 ASP.NET MVC 开发的 Windows Azure 或 Amazon EC2?