You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core Web API调用存储过程时n字段始终返回0的问题

问题根源分析

你的问题主要出在三个核心点:

  1. 只读属性无法被EF Core赋值:模型中的n字段只有get访问器,EF Core无法通过反射为其设置存储过程返回的值,导致始终默认初始化为0。
  2. 错误的实体映射配置:你将不存在于kosik表中的n设为主键,同时把实体映射到实际的kosik表,这会让EF Core优先按照表结构逻辑处理,而非存储过程的返回结果。
  3. 存储过程调用的参数传递风险:原代码用字符串拼接方式传递参数,存在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 04:11:17