EF Core为何生成TempId列?关联查询报错问题咨询
EF Core 查询生成不存在的TempId列问题分析
问题场景
实体与关联配置
[Table("Common_T229")] public class OrderDetail { [Column("F229_ID")] public int Id { get; set; } // ... 其他列 public virtual ICollection<OrderDetailTimeRange> TimeRanges { get; set; } = new Collection<OrderDetailTimeRange>(); } [Table("WP_OpPlanAuftragZeitrahmen")] public class OrderDetailTimeRange { [Column("Id")] public int Id { get; set; } // ... 其他列 public OrderDetail OrderDetail { get; set; } } public class E3kDbContext : DbContext { public DbSet<OrderDetail> OrderDetails { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<OrderDetail>() .HasMany(m => m.TimeRanges) .WithOne(d => d.OrderDetail) .HasForeignKey(d => d.OrderNumber) .OnDelete(DeleteBehavior.Cascade); } }
查询代码
public IEnumerable<OrderDetailDto> SearchData() { var e3k = ContextProviderService.GetE3kContext(); IQueryable<OrderDetail> query = e3k.OrderDetails.Include(x => x.TimeRanges); query = query.Take(5000); foreach (var data in query) { // ... 处理逻辑 } // ... }
错误信息
fail: 05.06.2023 18:30:30.800 RelationalEventId.CommandError[20102] (Microsoft.EntityFrameworkCore.Database.Command) Failed executing DbCommand (41ms) [Parameters=[@__p_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30'] SELECT [t].[F229_ID], [t].[F229_70], [t].[F229_34], [t].[F229_36], [t].[F229_03], [t].[F229_02], [t].[F229_89], [t].[TempId], [w].[Id], [w].[Von], [w].[Feiertag], [w].[AnzahlMitarbeiter], [w].[AuftragsNr], [w].[Samstag], [w].[Sonntag], [w].[Zeit], [w].[Bis] FROM ( SELECT TOP(@__p_0) [c].[F229_ID], [c].[F229_70], [c].[F229_34], [c].[F229_36], [c].[F229_03], [c].[F229_02], [c].[F229_89], [c].[TempId] FROM [Common_T229] AS [c] ) AS [t] LEFT JOIN [WP_OpPlanAuftragZeitrahmen] AS [w] ON [t].[TempId] = [w].[AuftragsNr] ORDER BY [t].[F229_ID] dbug: 05.06.2023 18:30:30.802 RelationalEventId.ConnectionClosing[20002] (Microsoft.EntityFrameworkCore.Database.Connection) Closing connection to database 'Dev_e3k_DietscheV6' on server '62.2.129.5\SQL2017,1433'. dbug: 05.06.2023 18:30:30.805 RelationalEventId.ConnectionClosed[20003] (Microsoft.EntityFrameworkCore.Database.Connection) Closed connection to database 'Dev_e3k_DietscheV6' on server '62.2.129.5\SQL2017,1433' (2ms). fail: 05.06.2023 18:30:30.820 CoreEventId.QueryIterationFailed[10100] (Microsoft.EntityFrameworkCore.Query) An exception occurred while iterating over the results of a query for context type 'Dik.WebApp.DataAccess.E3kDbContext'. Microsoft.Data.SqlClient.SqlException (0x80131904): Invalid column name 'TempId'.
问题
EF Core为何会生成不存在的TempId列?
原因分析
错误的核心是关联关系配置不完整,导致EF Core无法正确识别主表与子表的关联逻辑,进而生成了错误的SQL:
- 你在关联配置中指定子表外键为
d => d.OrderNumber,但OrderDetailTimeRange实体中并未定义该属性,EF Core尝试自动生成影子属性,但后续关联逻辑出现偏差; - 同时,你没有显式指定主表
OrderDetail用于关联的属性(默认EF Core会使用主表主键,但你的外键实际关联的是主表的非主键列),EF Core无法定位正确的关联字段,最终错误生成了不存在的TempId列。
另外,EF Core执行Take+Include查询时,需要先对主表分页再关联子表,这一步高度依赖正确的关联键来保证数据准确性,缺失的配置会直接导致SQL生成逻辑出错。
解决方法
步骤1:补全子表外键属性
在OrderDetailTimeRange实体中添加外键属性,并映射到数据库实际列名:
[Table("WP_OpPlanAuftragZeitrahmen")] public class OrderDetailTimeRange { [Column("Id")] public int Id { get; set; } // 添加外键属性,类型匹配数据库AuftragsNr列的实际类型 [Column("AuftragsNr")] public int OrderNumber { get; set; } // ... 其他列 public OrderDetail OrderDetail { get; set; } }
步骤2:补全主表关联属性(若缺失)
如果OrderDetail实体中没有对应数据库关联列的属性,需要添加并映射:
[Table("Common_T229")] public class OrderDetail { [Column("F229_ID")] public int Id { get; set; } // 添加主表关联列,类型匹配数据库对应列的实际类型 [Column("AuftragsNr")] public int OrderNumber { get; set; } // ... 其他列 public virtual ICollection<OrderDetailTimeRange> TimeRanges { get; set; } = new Collection<OrderDetailTimeRange>(); }
步骤3:完善关联配置
显式指定主表的关联属性与子表的外键属性,确保EF Core能正确识别关联逻辑:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<OrderDetail>() .HasMany(m => m.TimeRanges) .WithOne(d => d.OrderDetail) .HasPrincipalKey(m => m.OrderNumber) // 指定主表用于关联的属性 .HasForeignKey(d => d.OrderNumber) // 指定子表的外键属性 .OnDelete(DeleteBehavior.Cascade); }
内容的提问来源于stack exchange,提问作者BennoDual
相关产品推荐
相关产品推荐

