Entity Framework Core 2.1 - собственные типы и объекты вложенных значений - PullRequest
0 голосов
/ 06 декабря 2018

Я изучаю DDD, и учебник, которым я сейчас следую, реализован с использованием NHibernate, но, поскольку у меня не было опыта работы с ним, я решил пройти курс, используя EF Core 2.1.

Однако в настоящее время я немного застрял со следующим: у меня есть три класса Customer, которые являются сущностью и двумя объектами значения (CustomerStatus и внутри него объекта значения ExpirationDate) - какthis:

public class Customer : Entity
{
    //... constructor, other properties and behavior omitted for the sake of simplicity
    public CustomerStatus Status { get; set; }
}

public class CustomerStatus : ValueObject<CustomerStatus>
{
    // customer status is enum containing two values (Regular,Advanced)
    public CustomerStatusType Type { get; }
    public ExpirationDate ExpirationDate { get; }
}

public class ExpirationDate : ValueObject<ExpirationDate>
{
    //... constructor, other properties and behavior omitted for the sake of simplicity
    public DateTime? Date { get; private set; }
}

Когда я пытаюсь сделать следующее внутри моего DbContext:

modelBuilder.Entity<Customer>(table =>
{      
   table.OwnsOne(x => x.Status,
     name =>
     {
        name.Property(x => x.ExpirationDate.Date).HasColumnName("StatusExpirationDate");
        name.Property(x => x.Type).HasColumnName("Status");
     });
});

, я получаю следующую ошибку:

Выражение 'x => x.ExpirationDate.Date' не является допустимым выражением свойства.Выражение должно представлять простой доступ к свойству: 't => t.MyProperty'.
Имя параметра: propertyAccessExpression '

Помимо этого я пытался делать такие вещи, как:

table.OwnsOne(x => x.Status.ExpirationDate,
      name =>
      {
         name.Property(x => x.Date).HasColumnName("StatusExpirationDate");
      });
 table.OwnsOne(x => x.Status,
      name =>
      {
          name.Property(x => x.Type).HasColumnName("Status");
      });

Но это также приводит к:

Выражение 'x => x.Status.ExpirationDate' не является допустимым выражением свойства.Выражение должно представлять простой доступ к свойству: 't => t.MyProperty'.

Я также пробовал:

modelBuilder.Entity<Customer>()
                    .OwnsOne(p => p.Status, 
              cb => cb.OwnsOne(c => c.ExpirationDate));

Но и без удачи ..В любом случае, любая помощь будет принята с благодарностью, также, если это возможно, было бы действительно здорово, если бы кто-то мог объяснить, почему ни одна из моих попыток не работает?Заранее спасибо!

ОБНОВЛЕНИЕ

После того, как я сделал сначала, как было сказано в комментарии Ивана, я получил ошибку о CustomerStatus конструкторе класса, поэтому я добавил защищенный по умолчанию один.

После этого я начал получать сообщение об ошибке:

Поле 'k__BackingField' типа сущности 'CustomerStatus' доступно только для чтения и поэтому не может быть установлено.

Вотвнутри моего CustomerStatus класса, если это поможет:

public class CustomerStatus : ValueObject<CustomerStatus>
{
    public CustomerStatusType Type { get; }
    public ExpirationDate ExpirationDate { get; }

    public static readonly CustomerStatus Regular =
        new CustomerStatus(CustomerStatusType.Regular, ExpirationDate.Infinite);
    public bool IsAdvanced => Type == CustomerStatusType.Advanced && !ExpirationDate.IsExpired;

    private CustomerStatus(CustomerStatusType type, ExpirationDate expirationDate)
    {
        Type = type;
        ExpirationDate = expirationDate;
    }

    protected CustomerStatus()
    {

    }
    public static CustomerStatus Create(CustomerStatusType type, ExpirationDate expirationDate)
    {
        return new CustomerStatus(type, expirationDate);
    }

    public CustomerStatus Promote()
    {
        return new CustomerStatus(CustomerStatusType.Advanced, ExpirationDate.Create(DateTime.UtcNow.AddYears(1)).Value);
    }

    protected override bool EqualsCore(CustomerStatus other)
    {
        return Type == other.Type && ExpirationDate == other.ExpirationDate;

    }

    protected override int GetHashCodeCore()
    {
        return Type.GetHashCode() ^ ExpirationDate.GetHashCode();
    }
}

ОБНОВЛЕНИЕ

Все, что нужно, это добавить частные сеттеры в свойствах Type и ExpirationDate внутрикласса CustomerStatus и в сочетании с ответом Ивана работает как шарм.Большое спасибо!

1 Ответ

0 голосов
/ 06 декабря 2018

Ваши попытки не работают, потому что принадлежащие типы могут только быть настроены через их владельца сущность, а более конкретно, через их собственный конструктор, возвращенный методом OwnsOne или предоставленный какаргумент Action<T> аргумента метода OwnsOne конструктора сущностей владельца.

Таким образом, конфигурация должна выглядеть примерно так (обратите внимание на вложенные OwnsOne):

modelBuilder.Entity<Customer>(customer =>
{      
    customer.OwnsOne(e => e.Status, status =>
    {
        status.Property(e => e.Type).HasColumnName("Status");
        status.OwnsOne(e => e.ExpirationDate, expirationDate =>
        {
            expirationDate.Property(e => e.Date).HasColumnName("StatusExpirationDate");
        });
    });
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...