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)
如果希望在访问导航属性时自动加载关联数据,可以开启延迟加载:
- 安装NuGet包
Microsoft.EntityFrameworkCore.Proxies - 在DbContext的
OnConfiguring方法中启用延迟加载代理:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseLazyLoadingProxies() // 启用延迟加载代理 .UseSqlServer("你的数据库连接字符串"); }
- 将实体中的导航属性标记为
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
相关产品推荐
相关产品推荐

