将多个SQL SELECT结果映射到无键EF Core实体时出现序列无元素错误
问题根因
你遇到的报错是两个配置错误共同导致的:
- 存储过程Schema名称不匹配:你在
OnModelCreating中注册的SQL语句调用的是[dto].[GetForMonthlyBilling],但实际存储过程是创建在[dbo]schema下,EF执行查询时直接找不到对应存储过程,因此会立刻返回空结果,不会触发存储过程的40秒执行逻辑。 - EF原生无键实体映射不支持多结果集:你定义的
BillingAggregate实体包含4个集合属性,存储过程也返回了4个独立的结果集,但EF的ToSqlQuery配置仅支持单个结果集和实体属性一一对应的映射逻辑,无法自动将多个结果集填充到同一个实体的不同集合属性中。
修复步骤
1. 修正Schema引用
先修改OnModelCreating中的配置,将存储过程的schema改为实际的dbo:
modelBuilder.Entity<BillingAggregate>().ToSqlQuery("EXEC [dbo].[GetForMonthlyBilling]");
这个修改会解决存储过程无法被调用、立刻报错的问题。
2. 手动处理多结果集映射
你无法直接通过dbContext.BillingAggregate.FirstOrDefaultAsync()拿到聚合结果,需要手动读取存储过程返回的多个结果集,EF提供了Translate方法可以直接完成结果集到实体的映射,无需手写映射逻辑:
var billingAggregate = new BillingAggregate(); await using var command = dbContext.Database.GetDbConnection().CreateCommand(); command.CommandText = "[dbo].[GetForMonthlyBilling]"; command.CommandType = System.Data.CommandType.StoredProcedure; await dbContext.Database.OpenConnectionAsync(); await using var reader = await command.ExecuteReaderAsync(); // 映射第一个结果集:Customer billingAggregate.Customers = dbContext.Set<Customer>().Translate(reader).ToList(); // 切换到第二个结果集:Debt await reader.NextResultAsync(); billingAggregate.Debts = dbContext.Set<Debt>().Translate(reader).ToList(); // 切换到第三个结果集:Payment await reader.NextResultAsync(); billingAggregate.Payments = dbContext.Set<Payment>().Translate(reader).ToList(); // 切换到第四个结果集:Credit await reader.NextResultAsync(); billingAggregate.Credits = dbContext.Set<Credit>().Translate(reader).ToList();
注意事项
请确保存储过程中四个SELECT语句返回的字段名称、顺序、类型,和对应Customer/Debt/Payment/Credit实体的属性完全匹配,否则会出现映射失败的问题。
内容的提问来源于stack exchange,提问作者Serj Sagan
相关产品推荐
相关产品推荐

