EF Core 6关联SAP现有数据库Include查询结果不符问题排查
问题描述
在EF Core 6中映射SAP现有数据库的无关联表,已配置多对多与一对一实体关系,代码如下:
// 多对多关系配置 modelBuilder.Entity<Actividad>().ToTable("OCLG"); modelBuilder.Entity<Proyecto>().ToTable("OPRJ"); modelBuilder.Entity<Empleado>().ToTable("OHEM"); modelBuilder.Entity<Usuario>().ToTable("OUSR"); modelBuilder.Entity<Fase>().ToTable("[@ITAPROYSEG]"); modelBuilder.Entity<Actividad>() .HasKey(a => new { a.U_Proy, a.U_Fase, a.AttendUser}); modelBuilder.Entity<Actividad>() .HasOne(a => a.Proyecto) .WithMany(p => p.Actividades) .HasForeignKey(a => a.U_Proy); modelBuilder.Entity<Actividad>() .HasOne(a => a.Fase) .WithMany(f => f.Actividades) .HasForeignKey(a => a.U_Fase); modelBuilder.Entity<Actividad>() .HasOne(a => a.Usuario) .WithMany(u => u.Actividades) .HasForeignKey(a => a.AttendUser); // 一对一实体类 public class Empleado { public int EmpId { get; set; } [Key] public string U_CodEmpl { get; set; } public string Email { get; set; } public string FirstName { get; set; } public string MiddleName { get; set; } public string LastName { get; set; } public string NombreCompleto=>$"{FirstName} {MiddleName} {LastName}"; public Usuario Usuario { get; set; } } public class Usuario { [Key] [Column(TypeName ="smallint")] public int Internal_K { get; set; } [ForeignKey("Empleado")] public string User_Code { get; set; } public Empleado Empleado { get; set; } public List<Actividad> Actividades { get; set; } }
直接在数据库查询目标数据可得到479行,但使用以下EF Core查询仅能得到143条Actividades数据,原生SQL查询则能得到正确结果:
var empleado = _context.Empleados.Include(e => e.Usuario).ThenInclude(u => u.Actividades).FirstOrDefault(e => e.U_CodEmpl == codigoSAPEmpleado);
原因分析
- Actividad与Usuario的关联字段匹配错误:
当前配置中,Actividad的AttendUser外键被默认关联到Usuario的主键Internal_K,但两者类型不匹配(AttendUser为字符串,Internal_K为整数),且数据库中AttendUser实际应关联Usuario的User_Code字段。EF Core基于错误的关联条件生成SQL,导致大量符合条件的Actividad被过滤。 - 一对一关系配置不明确:
Empleado与Usuario的一对一关系仅通过属性标注了外键,但未在DbContext中显式定义关联规则,EF Core可能采用默认的主键关联逻辑,导致查询时的连接逻辑与数据库实际关联规则不符。
解决方法
1. 修正Actividad与Usuario的关联关系
修改Actividad的关系配置,明确指定关联Usuario的User_Code字段:
modelBuilder.Entity<Actividad>() .HasOne(a => a.Usuario) .WithMany(u => u.Actividades) .HasForeignKey(a => a.AttendUser) .HasPrincipalKey(u => u.User_Code); // 指定关联Usuario的User_Code字段而非主键
2. 完善Empleado与Usuario的一对一关系配置
在DbContext的OnModelCreating方法中显式配置一对一关系,明确双方的关联字段:
modelBuilder.Entity<Empleado>() .HasOne(e => e.Usuario) .WithOne(u => u.Empleado) .HasForeignKey<Usuario>(u => u.User_Code) .HasPrincipalKey<Empleado>(e => e.U_CodEmpl);
3. 验证生成的SQL(可选)
通过EF Core日志功能查看生成的SQL语句,确认关联条件与原生SQL一致:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.LogTo(Console.WriteLine, LogLevel.Information); }
内容的提问来源于stack exchange,提问作者kintela
相关产品推荐
相关产品推荐

