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

EF Core 8关联数据无法加载问题求助

解决EF Core 8中关联导航属性加载为空的问题

问题场景

使用.NET Entity Framework 8.0.1定义了Attraction、Address、Advert三个实体类,其中:

  • Attraction与Advert为一对多关系
  • Attraction与Address为一对一关系
    已通过迁移创建数据库,但执行查询时Attraction的Address始终为null,Adverts列表始终为空。

实体类代码

public class Attraction : BaseEntity
{
    [Required]
    [MaxLength(100)]
    public string Name { get; set; }

    [Required]
    [MaxLength(100)]
    public string Website { get; set; }

    public Address Address { get; set; }

    public ICollection<Advert> Adverts { get; } = new List<Advert>();

    public Attraction()
    {
    }
}

public class Address : BaseEntity
{
    [Required]
    public Guid AttractionId { get; set; }

    [Required]
    [MaxLength(100)]
    public string Line1 { get; set; }

    [Required]
    [MaxLength(100)]
    public string Line2 { get; set; }

    [Required]
    [MaxLength(100)]
    public string Line3 { get; set; }

    [Required]
    [MaxLength(100)]
    public string Line4 { get; set; }

    [Required]
    [MaxLength(100)]
    public string Line5 { get; set; }

    [Required]
    [MaxLength(16)]
    public string PostCode { get; set; }

    public Address()
    {
    }
}

public class Advert : BaseEntity
{
    [Required]
    public Guid AttractionId { get; set; }

    [Required]
    public string Description { get; set; }

    [Required]
    public DateTime DisplayFrom { get; set; }

    [Required]
    public DateTime DisplayTo { get; set; }

    [Required]
    public int DisplayType { get; set; }

    [Required]
    public string PanelColour { get; set; }

    public Advert()
    {
    }
}

基类BaseEntity代码

public class BaseEntity
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Required]
    public Guid Id { get; set; }
}

DbContext关系配置

protected override void OnModelCreating(ModelBuilder modelBuilder)
{          
    modelBuilder.Entity<Attraction>()
        .HasMany(e => e.Adverts)
        .WithOne()
        .HasForeignKey(e => e.AttractionId);

    modelBuilder.Entity<Attraction>()
        .HasOne(e => e.Address)
        .WithOne()
        .HasForeignKey<Address>(e => e.AttractionId);
}

原查询代码

public async Task<List<Attraction>> SelectAll()
{
    return await Task.Run(() => AppDbContext.Attractions.ToList());
}

解决方案

方法1:使用贪婪加载(Eager Loading)显式加载关联数据

EF Core默认不会自动加载导航属性关联的数据,需要通过Include方法指定要加载的关联实体,一次性查询所有需要的数据。同时,EF Core提供了原生异步方法ToListAsync,无需用Task.Run包装异步操作。

修改后的查询代码:

public async Task<List<Attraction>> SelectAll()
{
    return await AppDbContext.Attractions
        .Include(attraction => attraction.Address) // 加载一对一关联的Address
        .Include(attraction => attraction.Adverts) // 加载一对多关联的Adverts集合
        .ToListAsync();
}

方法2:开启延迟加载(Lazy Loading)

如果希望在访问导航属性时自动加载关联数据,可以开启延迟加载:

  1. 安装NuGet包Microsoft.EntityFrameworkCore.Proxies
  2. 在DbContext的OnConfiguring方法中启用延迟加载代理:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseLazyLoadingProxies() // 启用延迟加载代理
                  .UseSqlServer("你的数据库连接字符串");
}
  1. 将实体中的导航属性标记为virtual:
public class Attraction : BaseEntity
{
    // 其他属性不变
    public virtual Address Address { get; set; }
    public virtual ICollection<Advert> Adverts { get; } = new List<Advert>();
}

注意:延迟加载可能导致N+1查询问题(先查主实体,再逐个查询关联实体),需根据业务场景评估是否使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 18:18:37