简体   繁体   English

.NET Core 2.2中的DDD实体从属性中获取

[英]DDD entities in .NET Core 2.2 Get from properties

In the context of this question, if I use the word Entity I'm referring to a DDD entity, unless I explicitly state that I'm talking about an EF Core Entity 在这个问题的上下文中,如果我使用Entity这个词我指的是DDD实体,除非我明确声明我在谈论EF核心实体

I've been reading Microsoft's documentation on DDD patterns for .NET Core. 我一直在阅读Microsoft关于.NET Core的DDD模式的文档

I've also been looking at the GitHub repo they've created that contains the implementation described in the aforementioned documentation. 我也一直在查看他们创建的GitHub仓库 ,其中包含上述文档中描述的实现。 Specifically, I'm looking at the Order.cs aggregate (which is where the link points to). 具体来说,我正在查看Order.cs聚合(链接指向的位置)。

Background to the problem 问题的背景

I'm trying to understand how they've implemented Enumeration properties. 我试图了解他们如何实现Enumeration属性。

As you can see, the Enumeration type is similar to a Value Object but is a more convenient way (imho) of modelling attributes that behave like enums. 正如您所看到的, Enumeration类型类似于Value Object,但它是一种更方便的建模属性(imho),其行为类似于枚举。

Excerpt of a DDD entity that uses the Enumeration type (the full entity is in the repo link above): 使用Enumeration类型的DDD实体的摘录(完整实体位于上面的repo链接中):

public class Order
    : Entity, IAggregateRoot
{
    public OrderStatus OrderStatus { get; private set; }
    private int _orderStatusId;

    public Order()
    {
        _orderStatusId = OrderStatus.Submitted.Id;
    }
}

Problem 问题

Implementing a property this way means that whenever you get the OrderStatus property, it is null . 以这种方式实现属性意味着无论何时get OrderStatus属性,它都是null

I understand that encapsulating an Entity in DDD is of paramount concern, but surely that's only a concern when you're modifying it's state. 我知道在DDD中封装实体是最重要的,但当你修改它的状态时,这肯定只是一个问题。 Implementing a GetOrderStatus method seems like a very hacky way of just reading the property's value: 实现GetOrderStatus方法似乎只是一种非常简单的方法来读取属性的值:

public class Order
    : Entity, IAggregateRoot
{
    public OrderStatus OrderStatus { get; private set; }
    private int _orderStatusId;

    public Order()
    {
        _orderStatusId = OrderStatus.Submitted.Id;
    }

    public OrderStatus GetOrderStatus()
    {
        return Enumeration.FromValue<OrderStatus>(_orderStatusId);
    }
}

The only other thing I thought of was implementing the property like the below, but that breaks EF Core: 我想到的唯一另一件事就是像下面那样实现属性,但是打破了EF Core:

public class Order
    : Entity, IAggregateRoot
{
    public OrderStatus OrderStatus
    {
        get
        {
            return Enumeration.FromValue<OrderStatus>(_orderStatusId);
        }
        private set
        {
            Status = value;
        }
    }

    private int _orderStatusId;

    public Order()
    {
        _orderStatusId = OrderStatus.Submitted.Id;
    }
}

Is there a cleaner way to implement this? 有没有更清洁的方法来实现这一点?

If its a value type, why not treat it as Value Type (in EF Core Terminology Owned Entity )? 如果是值类型,为什么不将其视为值类型(在EF核心术语所有实体中 )?

Owned types are basically types without an identity (they are not identified by an ID, but by the whole of its value). 拥有的类型基本上是没有标识的类型(它们不是由ID标识,而是由它的整个值标识)。 Under the hood, each of the properties of the owned type, will be translated into a column name of the owned entity. 在引擎盖下,拥有类型的每个属性将被转换为拥有实体的列名。

This is excellent way to map value types to relation databases and you do not have to add an identity (id) column to your model. 这是将值类型映射到关系数据库的绝佳方法,您不必向模型添加标识(id)列。 Common examples are Address on an order. 常见的例子是订单上的Address

And if that doesn't suite your needs, there are Value Converter to convert a type to something that a database understands (ie enum -> string rather than enum id). 如果这不能满足您的需求,可以使用Value Converter将类型转换为数据库理解的类型(即enum - > string而不是enum id)。 This could be used to either convert an id (or string) to the proper value type and assign it. 这可以用于将id(或字符串)转换为正确的值类型并分配它。

Generally your problem comes from leaking persistence knowledge into your domain, __orderStatusId is relational storage related and has absolutely no meaning in your domain. 通常,您的问题来自于将持久性知识泄漏到您的域中, __orderStatusId与关系存储相关,并且在您的域中绝对没有任何意义。 That's something you absolutely HAVE TO to avoid when designing DDD models. 这是你绝对避免在设计DDD模型时的东西。

DDD models should never be influenced by persistence technology (ie having constructors that are required by the database or ORM mapper, having IDs on value types because they "map" to database tables, etc.). DDD模型永远不应受持久性技术的影响(即,具有数据库或ORM映射器所需的构造函数,在值类型上具有ID,因为它们“映射”到数据库表,等等)。

With a converter, you could convert the value type to id and id to value type, with something along the lines of 使用转换器,您可以将值类型转换为id和id转换为value类型,其中包含的内容

var converter = new ValueConverter<OrderStatus, int>(
    v => v.Id,
    v => Enumeration.FromValue<OrderStatus>(v));

modelBuilder
    .Entity<Order>()
    .Property(e => e.OrderStatus)
    .HasConversion(converter);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM