简体   繁体   中英

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

I've been reading Microsoft's documentation on DDD patterns for .NET Core.

I've also been looking at the GitHub repo they've created that contains the implementation described in the aforementioned documentation. Specifically, I'm looking at the Order.cs aggregate (which is where the link points to).

Background to the problem

I'm trying to understand how they've implemented Enumeration properties.

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.

Excerpt of a DDD entity that uses the Enumeration type (the full entity is in the repo link above):

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 .

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. Implementing a GetOrderStatus method seems like a very hacky way of just reading the property's value:

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:

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 )?

Owned types are basically types without an identity (they are not identified by an ID, but by the whole of its value). 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. Common examples are Address on an order.

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). This could be used to either convert an id (or string) to the proper value type and assign it.

Generally your problem comes from leaking persistence knowledge into your domain, __orderStatusId is relational storage related and has absolutely no meaning in your domain. That's something you absolutely HAVE TO to avoid when designing DDD models.

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.).

With a converter, you could convert the value type to id and id to value type, with something along the lines of

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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