Я изучаю 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
и в сочетании с ответом Ивана работает как шарм.Большое спасибо!