ASP.NET Core Web API调用存储过程时n字段始终返回0的问题
问题根源分析
你的问题主要出在三个核心点:
- 只读属性无法被EF Core赋值:模型中的
n字段只有get访问器,EF Core无法通过反射为其设置存储过程返回的值,导致始终默认初始化为0。 - 错误的实体映射配置:你将不存在于
kosik表中的n设为主键,同时把实体映射到实际的kosik表,这会让EF Core优先按照表结构逻辑处理,而非存储过程的返回结果。 - 存储过程调用的参数传递风险:原代码用字符串拼接方式传递参数,存在SQL注入隐患,同时也可能导致EF无法正确解析参数绑定。
解决方案
1. 修改模型属性,允许EF Core赋值
给n字段添加set访问器(如果使用EF Core 3.1及以上版本,也可以用init访问器,保证属性初始化后不可变):
public class PolozkaKosiku { [Column(TypeName = "int")] public int n { get; set; } // 或者用 get; init; 适用于EF Core 3.1+ [Column(TypeName = "numeric(19, 4)")] public decimal? Mnozstvi { get; set; } }
2. 修正实体配置为无键实体
因为这个实体仅用于接收存储过程的返回结果,不需要对应数据库中的表,将其配置为无键实体(EF Core 5.0及以上版本支持):
modelBuilder.Entity<PolozkaKosiku>() .HasNoKey(); // 标记为无键实体,无需指定主键
如果你使用的是EF Core 3.x及更早版本,没有HasNoKey方法,可以用ToView(null)模拟无表映射:
modelBuilder.Entity<PolozkaKosiku>() .ToView(null); // 告知EF该实体不对应任何实际表/视图
3. 优化存储过程调用代码
使用参数化查询避免SQL注入,同时正确调用无键实体的DbSet:
首先在你的DbContext中添加无键实体的DbSet:
public DbSet<PolozkaKosiku> PolozkyKosiku { get; set; }
然后修改调用方法:
public async Task<List<PolozkaKosiku>> GetAllAsync(string kodZakaznika) { var kodzParam = new SqlParameter("@kod_zakaznika", kodZakaznika); // 使用FromSqlRaw进行参数化存储过程调用 var result = await dbContext.PolozkyKosiku .FromSqlRaw("EXECUTE usp_kosik @kod_zakaznika = @param", kodzParam) .ToListAsync(); return result; }
补充说明
- 无键实体是EF Core专门用来处理查询结果(比如存储过程、视图、临时结果集)的模式,不需要对应数据库表结构,也无需主键。
- 确保存储过程返回的结果集中,列名和模型属性名完全匹配(注意大小写,SQL Server默认不区分大小写,但EF Core的属性映射是区分的)。
内容的提问来源于stack exchange,提问作者pepr
相关产品推荐
相关产品推荐

