Reputation: 1449
I use a value object to represent the Price
public record Price(decimal Amount, string Currency);
Then I have two entities with a price
public class Item
{
public Price { get; private set; }
// rest of properties
}
public class OrderPosition
{
public Price { get; private set; }
// rest
}
In the DB I would like to have these two tables
Items
| Id | Price_Amount | Price_Currency |
OrderPositions
| Id | Price_Amount | Price_Currency |
To achieve this i configured the Price to be an owned type of the item aswell as the order position:
public class ItemConfiguration : IEntityTypeConfiguration<Item>
{
public void Configure(EntityTypeBuilder<Item> builder)
{
builder.OwnsOne(i => i.Price);
}
}
public class ItemConfiguration : IEntityTypeConfiguration<OrderPosition>
{
public void Configure(EntityTypeBuilder<OrderPosition> builder)
{
builder.OwnsOne(op => op.Price);
}
}
This works all fine but EF gives me a warning when I have the same price on an item aswell as on the order position:
[09:47:59 WRN] The same entity is being tracked as different entity types 'Item.Price#Price' and 'OrderPosition.Price#Price' with defining navigations. If a property value changes, it will result in two store changes, which might not be the desired outcome.
And I understand the exception fully, it is even documented as a by design restriction: https://learn.microsoft.com/en-us/ef/core/modeling/owned-entities#by-design-restrictions
Instances of owned entity types cannot be shared by multiple owners (this is a well-known scenario for value objects that cannot be implemented using owned entity types).
But how do you solve this issue? Do I need to make a derived class for ItemPrice and OrderPositionPrice with implicit conversions to each other? This would work but I think this is not the best solution.
Upvotes: 2
Views: 1594
Reputation: 31
With the mentioned EF Core constraint, it is important not to pass the same value but a copy of it.
public record Price(decimal Amount, string Currency)
{
public Price Copy() => new(this);
}
// used
var price = new Price(42.0, "USD");
item.Price = price.Copy();
orderPosition.Price = price.Copy();
Upvotes: 1