EF Core一对一关系使用Include操作报错求助
问题描述
配置EF Core一对一关系后,使用Include关联查询时触发报错,其他类型关联查询正常,仅一对一场景出错。报错信息:
The expression 'p.BlogHeader' is invalid inside an 'Include' operation, since it does not represent a property access: 't => t.MyProperty'. To target navigations declared on derived types, use casting ('t => ((Derived)t).MyProperty') or the 'as' operator ('t => (t as Derived).MyProperty'). Collection navigation access can be filtered by composing Where, OrderBy(Descending), ThenBy(Descending), Skip or Take operations. For more information on including related data, see http://go.microsoft.com/fwlink/?LinkID=746393
实体类与模型配置代码:
// Principal (parent) public class Blog { public int Id { get; set; } public BlogHeader? BlogHeader { get; set; } // Reference navigation to dependent } // Dependent (child) public class BlogHeader { public int Id { get; set; } public int BlogId { get; set; } // Required foreign key property public Blog Blog { get; set; } = null!; // Required reference navigation to principal } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Blog>() .HasOne(e => e.Header) .WithOne(e => e.Blog) .HasForeignKey<BlogHeader>(e => e.BlogId); }
执行的Include操作代码:
public override Task<Blog?> GetByIdAsync(long blogId) { return DbSet .Include(p => p.BlogHeader) .SingleOrDefaultAsync(p => p.Id == blogId); }
错误原因
核心问题是实体类导航属性名称与模型配置中的导航属性名称不匹配:
- Blog类中定义的导航属性是
BlogHeader - 但在
OnModelCreating配置里,HasOne(e => e.Header)指向的是一个不存在的Header属性
EF Core无法识别Include(p => p.BlogHeader)为已配置的有效导航属性,因此抛出错误。
解决方案
两种修复方式二选一即可:
方式一:修改模型配置,匹配实体类属性名
将HasOne的参数改为e => e.BlogHeader,和Blog类中的属性名保持一致:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Blog>() .HasOne(e => e.BlogHeader) // 改为BlogHeader .WithOne(e => e.Blog) .HasForeignKey<BlogHeader>(e => e.BlogId); }
方式二:修改实体类属性名,匹配模型配置
把Blog类中的BlogHeader属性改名为Header,同时同步修改Include操作中的引用:
// 修改Blog实体类 public class Blog { public int Id { get; set; } public BlogHeader? Header { get; set; } // 改为Header } // 修改Include操作 public override Task<Blog?> GetByIdAsync(long blogId) { return DbSet .Include(p => p.Header) // 改为Header .SingleOrDefaultAsync(p => p.Id == blogId); }
内容的提问来源于stack exchange,提问作者Awybin

