У меня есть следующий граф сущностей:
Клиент -> Имеет несколько адресов -> У каждого адреса есть свойство навигации Страна
Я использовал строительные леса для обратного проектирования классов, поэтому проблем с настройками нет.
public class Customers {
public Customers() {
Addresses = new List<Addresses>();
}
public int CustomerId {
get; set;
}
public string FirstName {
get; set;
}
public string LastName {
get; set;
}
public int CustomerTypeId {
get; set;
}
public CustomerTypes CustomerType {
get; set;
}
public ICollection<Addresses> Addresses {
get; set;
}
}
public class Addresses {
public int AddressId {
get; set;
}
public int CustomerId {
get; set;
}
public int AddressTypeId {
get; set;
}
public string ZipPostalcode {
get; set;
}
public int CountryId {
get; set;
}
public AddressTypes AddressType {
get; set;
}
public Countries Country {
get; set;
}
}
public class Countries {
public int CountryId {
get; set;
}
public string Alpha2Code {
get; set;
}
public string Alpha3Code {
get; set;
}
public string EnglishName {
get; set;
}
public string FrenchName {
get; set;
}
}
У меня может быть клиент с двумя адресами - каждый с разными типами адресов, такими как «Дом» и «Бизнес», - но в одной стране (скажем, в США).
Ниже приведен упрощенный код, который вызывается для обновления графика - просто чтобы показать поток, я сначала извлекаю график клиента, вносю изменения и пытаюсь обновить (каждое действие в новом DbContext):
public static void Update_Using_TrackGraph(DbContextOptions<PolyglotContext> contextOptions) {
Customers customer;
using (var context = new PolyglotContext(contextOptions)) {
customer = context.Customers
.Include(x => x.CustomerType)
.Include(x => x.Addresses)
.ThenInclude(x => x.AddressType)
.Include(x => x.Addresses)
.ThenInclude(x => x.Country)
.AsNoTracking()
.SingleOrDefault(x => x.CustomerId == 1);
}
customer.EmailAddress = "new.email@avengers.com";
foreach (var address in customer.Addresses)
address.Line3 = "Thor Town";
using var ctx = new PolyglotContext(contextOptions);
ctx.ChangeTracker.Tracked += (s, e) => {
Console.WriteLine($"{e.Entry.Entity}: {e.Entry.State}");
};
ctx.ChangeTracker.StateChanged += (s, e) => {
Console.WriteLine($"{e.Entry.Entity}: {e.OldState} - {e.NewState}");
};
ctx.ChangeTracker
.TrackGraph(customer, e => {
e.Entry.State = e.Entry.IsKeySet ? EntityState.Modified : EntityState.Added;
});
ctx.SaveChanges();
}
Когда я пытаюсь прикрепить график, я получаю следующую ошибку:
The instance of entity type 'Countries' cannot be tracked because another instance with the same key value for {'CountryId'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.
После некоторого поиска я понимаю, что эта ошибка ожидается с EF 3.1. Здесь обсуждаются здесь и здесь .
Вопрос - Как мне решить эту проблему? Я попробовал следующие опции, и все они работают:
Опция 1 - Я изменил поведение TrackGraph следующим образом:
e.Entry.State = e.Entry.Entity.GetType() == typeof(Countries) ? EntityState.Detached
: (e.Entry.IsKeySet ? EntityState.Modified : EntityState.Added);
Опция 2 - При обновлении указывайте, что объект обновляется, а график не обновляется. Это означало бы обновление одной сущности за один раз
Есть ли другие доступные варианты? Я ищу опыт от тех, кто работал над подобным обновлением графика schenar ios?
Большое спасибо,