ASP.NET Core Web API:将FromSqlRaw返回的Cost统一转为字符串
解决存储过程返回Cost类型不一致的问题
针对存储过程返回Cost字段有时是decimal、有时是字符串的情况,有几个可靠的解决思路:
1. 修改存储过程,统一输出字符串类型
这是最稳妥的方案,在数据库层面直接把Cost字段转成字符串,从根源避免映射问题。修改存储过程中的SELECT语句,对Cost字段做强制类型转换:
-- 统一将Cost转为字符串,兼容decimal和字符串类型的源字段 SELECT Name, CONVERT(VARCHAR(50), Cost, 128) AS Cost, -- 128格式避免科学计数法,适配decimal转字符串 OrdQty, Model FROM 目标数据表
修改后存储过程返回的Cost始终是字符串类型,EF Core可以直接映射到DevOutput的Cost属性。
2. 在EF Core查询后手动转换
如果无法修改存储过程,可以先读取原始结果,再统一转换Cost字段的类型。注意不要直接用_context.DevOutput.FromSqlRaw(类型不匹配会抛出映射错误),改用Database.SqlQueryRaw读取动态类型后再映射:
[HttpPost] public async Task<ActionResult<IEnumerable<DevOutput>>> GetOutput(DevInput input) { // 使用参数化查询避免SQL注入 var devIdParam = new SqlParameter("@DevID", input.DevID); var sourceParam = new SqlParameter("@Source", input.Source); var rawResults = await _context.Database .SqlQueryRaw<dynamic>("Exec DevSearch @DevID, @Source", devIdParam, sourceParam) .ToListAsync(); var devOutputs = rawResults.Select(r => new DevOutput { Name = r.Name, Cost = Convert.ToString(r.Cost), // 统一转成字符串 OrdQty = r.OrdQty, Model = r.Model }).ToList(); return devOutputs; }
3. 配置EF Core值转换器
如果DevOutput是EF Core注册的无键实体,可以通过值转换器自动处理类型转换。在DevContext的OnModelCreating方法中添加配置:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<DevOutput>().HasNoKey(); // 标记为无键实体 modelBuilder.Entity<DevOutput>() .Property(d => d.Cost) .HasConversion( input => input, // 写入时无需转换(仅读取场景) dbValue => Convert.ToString(dbValue) // 读取时统一转字符串 ); }
配置完成后,即可继续使用原来的FromSqlRaw方式查询,EF会自动处理Cost的类型转换。
重要提醒:避免SQL注入
你当前的代码直接拼接input.DevID到SQL语句中,存在严重的SQL注入风险。必须改用参数化查询(如上述示例中SqlParameter的用法),这是Web API开发的基本安全规范。
内容的提问来源于stack exchange,提问作者J. Rent
相关产品推荐
相关产品推荐

