У меня есть две сущности, сущность Контакт , у которой есть свойство навигации Покупатель , которая может существовать, и сущность Покупатель , которая имеет свойство навигации Контакт , который должен существовать. Все покупатель имеют ровно один контакт , все контакт могут иметь ноль или один покупатель .
Проблема заключается в том, что при загрузке Контакт (с Покупателем ) Покупатель не может быть загружен через Eager или Явная загрузка.
public class Contact
{
public int ContactID { get; set; }
public string FirstName { get; set; } = null!;
public string LastName { get; set; } = null!;
public string Email { get; set; } = null!;
public virtual Buyer? Buyer { get; set; }
}
public class Buyer
{
public int BuyerID { get; set; }
public string CompanyName { get; set; } = default!;
public string ProductName { get; set; } = default!;
public int ContactID { get; set; }
public virtual Contact Contact { get; set; } = new Contact();
}
Когда я создаю сущности:
// existing Contact already initialized with Buyer == null and added
var newBuyer = new Buyer() { CompanyName = "Acme", ProductName = "Anvil" };
newBuyer.ContactID = contactID;
// Load the reference to the Contact
newBuyer.Contact = await _context.Contacts.SingleOrDefaultAsync(c => c.ContactID == contactID);
// error checking elided (but in this test it is not failing)
// newBuyer.Contact.Buyer is null if examined
_context.Buyers.Add(newBuyer);
// newBuyer.Contact.Buyer is now newBuyer, automatic fix-up
await _context.SaveChangesAsync();
При взгляде на базовую базу данных все происходит как ожидалось.
Теперь я пытаюсь загрузить контакт и свойства навигации двумя разными способами, ожидая автоматических исправлений c:
Contact = await _context.Contacts.FindAsync(id);
// The Contact.Buyer is null here as expected, so explicitly Load
_context.Entry(Contact).Reference(c => c.Buyer).Load();
// The Contact.Buyer is still null here, so try DetectChanges
_context.ChangeTracker.DetectChanges();
// The Contact.Buyer is still null here, so try again with Eager Loading
Contact = await _context.Contacts.Include(c => c.Buyer).FirstOrDefaultAsync(m => m.ContactID == id);
// The Contact.Buyer is still null here! What is wrong?
При трассировке в отладчике первый явный метод Load () видит Покупателя как свойство навигации и успешно загружает его в память. Также глядя на _contacts.Buyers показывает, что он находится в памяти.
DetectChanges был добавлен на всякий случай, это не имеет значения.
Загрузка Eager с помощью Include также не вызывает исправлений.
Ленивая загрузка также была опробована и не удалась.
Кто-нибудь знает, как заставить работать автоматическое исправление c?
Свободный API:
modelBuilder.Entity<Contact>()
.HasKey("ContactID");
modelBuilder.Entity<Buyer>()
.HasKey(p => p.BuyerID);
modelBuilder.Entity<Buyer>()
.HasOne<Contact>(p => p.Contact)
.WithOne("Buyer")
.HasForeignKey("Buyer", "ContactID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
Примечания: EF Core 3.1.3 Net Core API 3.1.0 Включить Nullable
[Редактировать] Добавив следующую строку кода перед FindAsyn c это приводит к загрузке всего Покупателя в память / кэш, после чего покупатель Contact.Buyer автоматически исправляется после первого FindAsyn c (). Это показывает, что исправления могут произойти. Но я не хочу принудительно загружать всю таблицу.
var test = _context.Buyers.ToList();