使用EF Core 6调用MS SQL Server存储过程返回无效表问题求助
问题排查与解决方案
以下是针对调用存储过程返回无效表格问题的具体排查方向和解决方法:
1. 列名与数据类型映射不匹配
存储过程返回的结果集必须和目标类的属性名称、数据类型完全匹配,否则会出现映射失败:
- 检查
dbo.Ingredients.Count的SQL数据类型:如果SQL中是int/decimal类型,而实体类用double?,会导致类型转换错误。建议将实体的Count属性修改为和SQL一致的类型,比如decimal?或int?。 - 确认存储过程返回的列名和实体属性名完全一致(SQL Server默认不区分大小写,但EF Core映射会严格匹配名称)。
修改后的实体示例:
public class Ingredient { public int Id { get; set; } public string? Product { get; set; } public string? Material { get; set; } public decimal? Count { get; set; } // 匹配SQL中的数据类型 }
2. 修正EF Core调用存储过程的方式
FromSqlRaw是针对数据库实体对应的DbSet设计的,如果Ingredient是存储过程返回的DTO而非数据库表实体,直接调用会导致EF Core误判结构。正确做法是使用Database.SqlQuery(EF Core 6+支持),并加上EXEC关键字确保SQL Server识别为存储过程调用:
List<Ingredient> ingredients = await _context.Database .SqlQuery<Ingredient>("EXEC SP_Ingredient_Select") .ToListAsync(); return View(ingredients);
3. 验证存储过程本身的正确性
直接在SQL Server中执行EXEC SP_Ingredient_Select,确认:
- 是否有正常数据返回
- 列名、数据类型是否符合预期
- JOIN关联条件是否正确(
dbo.Ingredients.Product = dbo.Products.Id、dbo.Ingredients.Material = dbo.Materials.Id),避免因外键关联错误导致无数据或错误结果。
4. 区分实体类与DTO类
如果Ingredient是对应dbo.Ingredients表的数据库实体,那它的属性和存储过程返回的结果结构完全不符(实体应存外键ID,而非名称字符串)。此时需要创建专用DTO类接收存储过程结果:
// 新建DTO类,仅用于接收存储过程返回结果 public class IngredientDto { public int Id { get; set; } public string? Product { get; set; } public string? Material { get; set; } public decimal? Count { get; set; } }
调用时改用DTO:
List<IngredientDto> ingredients = await _context.Database .SqlQuery<IngredientDto>("EXEC SP_Ingredient_Select") .ToListAsync(); return View(ingredients);
内容的提问来源于stack exchange,提问作者dmmhlchk
相关产品推荐
相关产品推荐

