DDD сущности в .NET Core 2.2 Получить из свойств - PullRequest
0 голосов
/ 04 мая 2019

В контексте этого вопроса, если я использую слово Сущность Я имею в виду сущность DDD, если только я явно не заявляю, что говорю об основной сущности EF

Я читал документацию Microsoft по шаблонам DDD для .NET Core.

Я также смотрел на репозиторий GitHub , который они создали, который содержит реализацию, описанную в вышеупомянутой документации. В частности, я смотрю на совокупность Order.cs (на которую указывает ссылка).

Предыстория проблемы

Я пытаюсь понять, как они реализовали Enumeration свойств.

Как вы можете видеть, тип Enumeration похож на объект Value, но является более удобным способом (imho) моделирования атрибутов, которые ведут себя как перечисления.

Выдержка из сущности DDD, которая использует тип Enumeration (полная сущность находится в ссылке на репо выше):

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

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

Проблема

Реализация свойства таким способом означает, что всякий раз, когда вы get свойство OrderStatus, это null.

Я понимаю, что инкапсуляция сущности в DDD имеет первостепенное значение, но, безусловно, это касается только изменения вашего состояния. Реализация метода 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);
    }
}

Единственное, о чем я подумал, это реализация свойства, подобного приведенному ниже, но это нарушает 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;
    }
}

Есть ли более чистый способ реализовать это?

1 Ответ

0 голосов
/ 06 мая 2019

Если это тип значения, почему бы не рассматривать его как тип значения (в базовой терминологии EF Owned Entity )?

Принадлежащие типы - это, в основном, типы без идентификатора (они не идентифицируются идентификатором, но в целом его значением). Под капотом каждое из свойств принадлежащего типа будет переведено в имя столбца принадлежащего объекта.

Это отличный способ сопоставления типов значений с базами данных отношений, и вам не нужно добавлять столбец идентификаторов (id) в вашу модель. Типичными примерами являются Address для заказа.

И если это не соответствует вашим потребностям, есть Преобразователь значений для преобразования типа во что-то, что база данных понимает (т.е. enum -> string, а не enum id). Это можно использовать для преобразования идентификатора (или строки) в правильный тип значения и присвоения ему.

Обычно ваша проблема связана с утечкой знаний о постоянстве в ваш домен, __orderStatusId связана с реляционным хранилищем и не имеет абсолютно никакого значения в вашем домене. Это то, чего вы абсолютно ДОЛЖНЫ избегать при разработке моделей DDD.

Модели DDD никогда не должны подвергаться влиянию технологии персистентности (т. Е. Иметь конструкторы, необходимые для базы данных или преобразователя ORM, иметь идентификаторы для типов значений, поскольку они "отображаются" в таблицах базы данных и т. Д.).

С помощью конвертера вы можете преобразовать тип значения в id и id в тип значения, что-то вроде

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

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