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

.NET Minimal API执行存储过程重复返回首行数据求助

.NET Minimal API调用存储过程重复返回第一行数据问题排查与解决

问题描述

刚接触API开发,在.NET Minimal API中调用存储过程时遇到异常:存储过程能正常执行,但Swagger返回的结果重复第一行数据,直接在SQL Server中执行该存储过程则结果正常。使用的代码如下:

app.MapGet("/AllProducts/{LocationID}", (DataContext context, int LocationID) => context.AllLocationProducts.FromSqlRaw($"GetProducts @LocationNumber='{LocationID}'").ToListAsync());

核心原因与解决步骤

这种问题几乎都是EF Core实体映射的主键配置异常导致——EF Core依赖主键来区分不同实体实例,若实体无正确主键、或存储过程返回结果的主键值重复,EF会将所有行识别为同一个实体,最终返回重复的第一行数据。

  • 检查实体主键配置
    确保AllLocationProducts实体类已正确标记主键:

    • 用特性标记:在实体的唯一标识字段上添加[Key]特性,例如:
      public class AllLocationProducts
      {
          [Key]
          public int ProductId { get; set; } // 替换为你的实际主键字段
          // 其他属性
      }
      
    • 用Fluent API配置:在DataContext的OnModelCreating方法中指定主键:
      protected override void OnModelCreating(ModelBuilder modelBuilder)
      {
          modelBuilder.Entity<AllLocationProducts>()
              .HasKey(p => p.ProductId); // 替换为你的实际主键字段
      }
      

    如果存储过程返回的结果无单一唯一主键,可考虑使用复合主键,或在存储过程中通过ROW_NUMBER()生成唯一标识字段。

  • 修正参数传递方式(避免SQL注入+潜在类型问题)
    原代码用字符串拼接传递参数,存在SQL注入风险且可能引发类型转换异常,改为参数化调用:

    app.MapGet("/AllProducts/{LocationID}", async (DataContext context, int LocationID) => 
        await context.AllLocationProducts
            .FromSqlRaw("EXEC GetProducts @LocationNumber = {0}", LocationID)
            .ToListAsync());
    

    或更明确的SqlParameter方式:

    app.MapGet("/AllProducts/{LocationID}", async (DataContext context, int LocationID) => 
    {
        var locationParam = new SqlParameter("@LocationNumber", LocationID);
        return await context.AllLocationProducts
            .FromSqlRaw("EXEC GetProducts @LocationNumber", locationParam)
            .ToListAsync();
    });
    
  • 验证存储过程返回结果
    在SQL Server中执行EXEC GetProducts @LocationNumber = N'你的测试LocationID',检查结果集中主键字段的值是否唯一。若存在重复,需修改存储过程确保每一行的主键值唯一。

  • 临时排查:禁用查询跟踪
    若怀疑是EF跟踪机制导致的问题,可临时禁用跟踪测试:

    app.MapGet("/AllProducts/{LocationID}", async (DataContext context, int LocationID) => 
        await context.AllLocationProducts
            .AsNoTracking()
            .FromSqlRaw("EXEC GetProducts @LocationNumber = {0}", LocationID)
            .ToListAsync());
    

    若此方法返回正常,说明确实是实体识别问题,需回到第一步修正主键配置。

内容的提问来源于stack exchange,提问作者nees007

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 06:18:30