Ho creato un'entità che accetta un oggetto valore come parametro nel suo costruttore, tuttavia quando aggiungo l'entità al contesto db genera la seguente eccezione.
InvalidOperationException: nessun costruttore adatto trovato per il tipo di entità> 'BasketItem'. I seguenti costruttori avevano parametri che non potevano essere> associati a proprietà del tipo di entità: impossibile associare 'price' in> 'BasketItem (ID guida, ID prodotto Guid, DateTimeOffset aggiuntoAt, Prezzo monetario)'.
Ho provato builder.OwnsOne(x => x.Price);
nella configurazione del tipo. Tieni presente che sto utilizzando il provider di archiviazione in memoria.
BasketItem.cs
public sealed class BasketItem : Entity
{
public Guid ProductId { get; private set; }
public DateTimeOffset AddedAt { get; private set; }
public Money Price { get; private set; }
public BasketItem(Guid id, Guid productId, DateTimeOffset addedAt, Money price) : base(id)
{
ProductId = productId;
AddedAt = addedAt;
Price = price;
}
}
Money.cs
public sealed class Money : ValueObject
{
public decimal Value { get; private set; }
public string CurrencyCode { get; private set; }
public Money(decimal value, string currencyCode)
{
Value = value;
CurrencyCode = currencyCode;
}
protected override IEnumerable<object> GetAtomicValues()
{
return new object[] { Value, CurrencyCode };
}
}
L'implementazione di oggetti valore DDD con tipi di entità posseduti da EF Core presenta diverse carenze, a causa del fatto che i tipi di entità posseduti da EF Core sono ancora considerati entità e le proprietà che restituiscono i tipi di entità possedute sono trattate come proprietà di navigazione .
In questo caso particolare, il problema è causato dall'ultima cosa sopra menzionata insieme alla seguente limitazione dei costruttori del tipo di entità
Alcune cose da notare:
- EF Core non può impostare le proprietà di navigazione (come Blog o Post sopra) utilizzando un costruttore.
La soluzione / soluzione consiste nel fornire un costruttore privato speciale che verrà utilizzato da EF:
public BasketItem(Guid id, Guid productId, DateTimeOffset addedAt, Money price) : this(id, productId, addedAt)
{
Price = price;
}
/// <summary>
/// EF constructor
/// </summary>
private BasketItem(Guid id, Guid productId, DateTimeOffset addedAt) : base(id)
{
ProductId = productId;
AddedAt = addedAt;
}
E ovviamente usa l'attributo [Owned]
o l'API OwnsOne
per mappare il Money
come tipo di entità posseduta.