.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
相关产品推荐
相关产品推荐

