Entity Framework Core 不会自动修复导航

Entity Framework Core doesn't automatically fix-up navigation

我有两个实体,一个实体 Contact 可能存在导航 属性 Buyer,一个实体具有必须存在的导航 属性 联系人买家。所有买家都有一个联系人,所有联系人可能有零个或一个买家的.

出现的问题是,当加载 Contact(有 Buyer)时,Buyer 无法通过 EagerExplicit 加载。

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();

查看底层数据库,一切都符合预期。

现在我尝试以两种不同的方式加载联系人和导航属性,期望自动修复:

 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() 将 Buyer 视为导航 属性 并成功加载 它进入记忆。还看_contacts.Buyers表明在内存中
添加 DetectChanges 只是为了以防万一,没有任何区别。
使用 Include 的急切加载也不会导致修复。
也尝试过延迟加载,但失败了。

有谁知道如何让自动修复工作?

流利的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 可空启用

[编辑] 通过在 FindAsync 之前添加以下代码行,它会导致所有买家加载到 memory/cache,然后 Contact.Buyer 买家会在第一个 FindAsync() 之后自动修复.这表明可能会发生修正。但是又不想强行加载整个table.

var test = _context.Buyers.ToList();

@IvanStoev 正确评论问题出在以下行:

public virtual Contact Contact { get; set; } = new Contact();

替换为:

public virtual Contact Contact { get; set; } = null!;

所有自动修正都在工作。

另见: