У меня есть объект значения и сущность, которая использует указанный объект значения. Я использую шаблон нулевого объекта для указанного объекта значения. Мой объект значения выглядит примерно так:
public class Reference {
public static Reference Empty;
private string _value;
static Reference() {
Empty = new Reference(String.Empty);
}
public Reference(string value) {
_value = value;
}
private Reference() {
_value = default!;
}
public string Value => _value;
}
А моя сущность:
public class Payment {
private Guid _id;
private decimal _amount;
private Reference _reference;
public Payment(decimal amount) {
_id = Guid.Empty; //ef will generate the id
_reference = Reference.Empty;
_amount = amount;
}
private Payment() {
_id = default;
_reference = default!;
_amount = default;
}
public Guid Id => _id;
public decimal Amount => _amount;
public Reference Reference => _reference;
}
Теперь класс Reference
настроен в EF-Core с использованием отношения OwnsOne
. Примерно так:
internal class PaymentConfiguration
: IEntityTypeConfiguration<Payment> {
public void Configure(EntityTypeBuilder<Payment> builder) {
builder.ToTable("Payments");
builder.HasKey(x => x.Id);
builder.OwnsOne(x => x.Reference, y => {
y.Property(z => z.Value)
.HasColumnName("Reference")
.IsRequired();
});
}
}
Добавление платежа выглядит следующим образом:
var payment = new Payment(5000m);
_context.Payments.Add(payment);
await _context.SaveChangesAsync();
Это работает довольно хорошо, но в тот момент, когда я пытаюсь добавить два платежа:
_context.Payments.Add(new Payment(5000m));
_context.Payments.Add(new Payment(6000m));
await _context.SaveChangesAsync();
Я получаю сообщение об ошибке:
The property 'PaymentId' on entity type 'Reference' is part of a key and so cannot be modified or marked as modified. To change the principal of an existing entity with an identifying foreign key first delete the dependent and invoke 'SaveChanges' then associate the dependent with the new principal.
После такой большой отладки я обнаружил, что проблема в том, что оба объекта Payment
используют один и тот же ссылочный объект, определенный Reference.Empty
, Действительно, если я изменю свой код на следующий, проблема прекратится:
public Payment(decimal amount) {
_id = Guid.Empty; //ef will generate the id
_reference = new Reference(String.Empty); //instead of Reference.Empty;
_amount = amount;
}
Я не знаю внутреннюю работу EF-Core, но если бы мне пришлось угадывать, я бы сказал, что как-то EF-Core создает производный класс и добавляет вещи, чтобы он работал, поэтому мой объект Reference.Empty
изменяется, что влияет на каждый объект Payment
, использующий его. Это означает, что я не могу использовать шаблон нулевого объекта как есть.
Теперь мой вопрос. Есть ли способ настроить Ef-Core, чтобы остановить это поведение? Или есть обходной путь для использования шаблона нулевого объекта? Я использую C # 8, NET Core 3 и Entity Framework Core 3. Заранее спасибо.