ядро ef устанавливает один и тот же объект значения для нескольких объектов

#c# #entity-framework #.net-core #entity-framework-core #ef-core-3.1

#c# #entity-framework #.net-core #entity-framework-core #ef-core-3.1

Вопрос:

Я использую EF Core 3.1 с CosmosDB и пытаюсь реализовать некоторые подходы DDD. У меня есть объект Customer

 public class Customer : Entity, IAggregateRoot
{
    // For EF Core
    protected Customer()
    {
    }

    public Customer(Guid id, string name, Address address)
    {
        CustomerId = id;
        Name = name;
        SetAddress(address);
    }

    public Guid CustomerId { get; private set; }
    public string Name { get; private set; }
    public Address Address { get; private set; }

    public void SetAddress(Address address)
    {
        Address = address ?? throw new ValidationException(nameof(Address), "Required");
    }
}
  

и адресует как объект значения:

 public class Address
{
    // For EF Core
    public Address()
    {
    }

    public Address(string street, string city, string state, string country)
    {
        Street = street;
        City = city;
        State = state;
        Country = country;
    }

    public string Street { get; private set; }
    public string City { get; private set; }
    public string State { get; private set; }
    public string Country { get; private set; }
}
  

Конфигурация объекта:

 builder.ToContainer("Customers");
builder.HasNoDiscriminator();
builder.HasKey(x => x.CustomerId);    
builder.OwnsOne(x => x.Address);
  

Мне нужно получить список клиентов из базы данных, а затем обновить для них адрес.

 var customers = await _repository.GetAll(x => x.Name == "Joe", cancellationToken);
var address = new Address("St1", "London", "", "UK");
foreach (var customer in customers)
{
   customer.SetAddress(address);
   _repository.Update(customer);
}
await _repository.Save(cancellationToken);
  

Допустим, у меня есть только 2 элемента в customers . После того, как Save я получу null для первого элемента и точный адрес для второго. Не могу понять, почему. Но когда я создаю новый адрес для каждого элемента в цикле, тогда все работает нормально

 foreach (var customer in customers)
{
   customer.SetAddress(new Address("St1", "London", "", "UK"););
   _repository.Update(customer);
}
  

Не могли бы вы подсказать, почему я должен каждый раз создавать новый объект?

Комментарии:

1. Почему у вас есть ключ у вас есть только одна запись для каждого ключа: builder. hasKey(x => x.CustomerID);

2. Что вы имеете в виду? Это похоже на первичный ключ для каждого клиента. Это не ключ раздела, поэтому я думаю, что в данном случае это не проблема

Ответ №1:

Я полагаю, это потому, что EF Core отслеживает экземпляры классов.

На 1-й итерации вы вводите адрес в 1-го клиента, и EF Core начинает отслеживать его. И когда вы передаете его 2-му клиенту, EF Core распознает это как перемещение одного и того же адреса от одного клиента к другому.

Комментарии:

1. Спасибо. Есть ли какое-либо решение?

2. Просто создайте новый экземпляр.

3. может быть, я могу как-то отключить отслеживание? Что, если список содержит 1000 элементов? Это создаст 1000 одинаковых объектов

4. Если вы отключите отслеживание, ef core не сможет понять, изменилась ли ваша сущность. Что у тебя внутри _repository.Update(customer); ?

5. _контекст. Запись (клиент). Состояние = EntityState. Измененный;