You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF Core自引用关系:Details视图Child为Null但Index视图正常

问题排查:Contact自引用关系中Details方法无法访问Child的FullName

我为Contact模型设置了自引用关系(一个联系人可与其他联系人建立关联)。在控制器的GET: Details方法中,能获取到ChildId,但无法访问Child对应的Contact的FullName;而GET Index方法中Child不为Null,可正常访问FullName。


控制器代码

Details方法查询

var contact = await _context.Contacts
                            .Include(r => r.RelationshipsAsParent)
                            .ThenInclude(t => t.RelationshipType)
                            .FirstOrDefaultAsync(m => m.Id == id);

Index方法查询

return _context.Contacts != null 
           ? View(await _context.Contacts
                                .Include(r => r.RelationshipsAsParent)
                                .ThenInclude(t => t.RelationshipType)
                                .ToListAsync()) 
           : Problem("Entity set 'ApplicationDbContext.Contacts' is null.");

模型代码

public class Contact
{
    public int Id { get; set; }

    public string? FirstName { get; set; }
    public string? LastName { get; set; }

    [NotMapped]
    public string? FullName { get { return $"{FirstName} {LastName}"; } }

    // Navigation properties for relationships where this contact is the parent
    public virtual List<Relationship>? RelationshipsAsParent { get; set; }

    // Navigation properties for relationships where this contact is the child
    public virtual List<Relationship>? RelationshipsAsChild { get; set; }
}

public class Relationship
{
    public int Id { get; set; }

    public int? ParentId { get; set; }
    public virtual Contact? Parent { get; set; }

    // Foreign key and navigation property for the child contact
    public int? ChildId { get; set; }
    public virtual Contact? Child { get; set; }

    // Navigation property for the relationship type (assuming there's a RelationshipType entity)
    public int? RelationshipTypeId { get; set; }
    public virtual RelationshipType? RelationshipType { get; set; }
}

public class RelationshipType
{
    public int Id { get; set; }
    public string? Type { get; set; }

    public virtual List<Relationship>? Relationships { get; set; } = new List<Relationship>();
}

Fluent API配置

modelBuilder.Entity<Relationship>(b =>
        {
            modelBuilder.Entity<Relationship>()
            .HasOne(r => r.Parent)
            .WithMany(c => c.RelationshipsAsParent)
            .HasForeignKey(r => r.ParentId)
            .OnDelete(DeleteBehavior.Restrict);

            modelBuilder.Entity<Relationship>()
            .HasOne(r => r.Child)
            .WithMany(c => c.RelationshipsAsChild)
            .HasForeignKey(r => r.ChildId)
            .OnDelete(DeleteBehavior.Restrict);
        });

视图代码

Detail视图

<h3>Relationships</h3>
    <ul>
        @if (@Model.RelationshipsAsParent.Count > 0)
        {
            @for (int j = 0; j < Model.RelationshipsAsParent.Count; j++)
            {
                <li>@Model.RelationshipsAsParent[j].ChildId: @Model.RelationshipsAsParent[j].RelationshipType.Type</li>
            }
        }
        else
        {
            <li>No Relationships</li>
        }
    </ul>

Index视图

<div class="row ms-5">
  <ul>
  @if (item.RelationshipsAsParent != null)
    {
    @for (int j = 0; j < item.RelationshipsAsParent.Count; j++)
    {
    <li>@item.RelationshipsAsParent[j].Child.FullName: @item.RelationshipsAsParent[j].RelationshipType.Type</li>
    }
    }
    else
   {
    <li>No Relationships</li>
   }
  </ul>
</div>

问题原因及解决办法

问题核心是显式加载范围不足,结合延迟加载的触发条件导致差异:

  1. Index方法查询所有Contact时,Child对应的Contact实例已被加载到上下文,延迟自动触发,Child导航属性可正常访问;而Details方法仅查询单个Contact,上下文无对应Child实例,且未显式IncludeChild导航属性,因此Child为Null。
  2. 解决办法是在Details方法的查询中,显式加载Relationship的Child导航属性:

修改后的Details方法查询:

var contact = await _context.Contacts
                            .Include(r => r.RelationshipsAsParent)
                                .ThenInclude(t => t.RelationshipType)
                            .Include(r => r.RelationshipsAsParent)
                                .ThenInclude(t => t.Child) // 新增此行,显式加载Child
                            .FirstOrDefaultAsync(m => m.Id == id);

或使用EF Core 5+支持的简洁语法:

var contact = await _context.Contacts
                            .Include(r => r.RelationshipsAsParent)
                                .ThenInclude(t => new { t.RelationshipType, t.Child })
                            .FirstOrDefaultAsync(m => m.Id == id);

修改后即可确保RelationshipsAsParent中每个Relationship的Child被加载,视图里就能正常访问Child.FullName。

内容的提问来源于stack exchange,提问作者David

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 08:57:35