EF Core 将具有 null 属性的实体从外键检索到同一模型

kha*_*osh 3 asp.net-mvc entity-framework-core asp.net-core-3.1

当我查询数据库以检索记录时,并且模型包含一个作为同一类型的外键的属性,该属性返回null. 我做错了什么?

我有这个模型类:

public class Customer
{
    public int ID { get; set; }
    
    [ForeignKey("ParentID")]
    public virtual Customer Parent { get; set; }

    public List<Contact> Contacts { get; set; }

    [Required]
    public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

与基础表:

CREATE TABLE [dbo].[Customer] 
(
    [ID]       INT IDENTITY (1, 1) NOT NULL,
    [ParentID] INT NULL,
    [Name]     NVARCHAR(MAX) NOT NULL,

    CONSTRAINT [PK_Customer] 
        PRIMARY KEY CLUSTERED ([ID] ASC),
    CONSTRAINT [FK_Customer_Customer_ParentID] 
        FOREIGN KEY ([ParentID]) REFERENCES [dbo].[Customer] ([ID])
)
Run Code Online (Sandbox Code Playgroud)

它是使用 EF Core 代码优先迁移生成的。

CustomersController尝试:

public async Task<IActionResult> Details(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    // returns the correct customer with null Parent property which causes...
    var customer = await _context.Customer
                                 .FirstOrDefaultAsync(m => m.ID == id); 

    if (customer == null)
    {
        return NotFound();
    }

    var vm = new CustomerViewModel(customer); // ... NRE to be thrown here

    return View(vm);
}
Run Code Online (Sandbox Code Playgroud)

即使该数据存在于表中:

ID  ParentID  Name
--------------------------
5   1         ParentCo
7   5         ChildCo
Run Code Online (Sandbox Code Playgroud)

Gab*_*ico 5

尝试这个

var result = await _context.Customer.Include(x => x.Parent).FirstOrDefaultAsync(x => x.Id == id);

Run Code Online (Sandbox Code Playgroud)

但如果这不起作用

var customer = await _context.Customer.FirstOrDefaultAsync(
        .FirstOrDefaultAsync(m => m.ID == id); );

if (customer != null)
{
   var parent = await _context.Customer.FirstOrDefaultAsync(x => x.ParentId == customer.Id);

   if (parent != null)
   {
       customer.Parent = parent;
   }
}
else
{
    return NotFound();
}


Run Code Online (Sandbox Code Playgroud)

  • @khargoosh 它被映射为外部表,并且 ```Include(...)``` 被翻译为 ```SQL Join 语句```。不自动包含它的原因是为了性能。想象一下,如果您有 6-7 个表自动包含在“Customer”表中。因此,目的是将查询限制在主表中,并通过“包含”,您将仅添加所需的内容。 (2认同)