EF Core调用SaveAll保存时float参数无效异常解决方法
解决方案
首先明确:默认情况下C# double 类型映射SQL Server float 类型是完全符合EF Core官方映射约定的,不需要第一时间修改数据类型,这个报错90%以上是传入了SQL Server float类型不支持的非法值导致的。
核心触发原因
SQL Server的float类型不支持存储C# double的三个特殊值:
double.NaN(非数字)double.PositiveInfinity(正无穷)double.NegativeInfinity(负无穷)
EF Core不会在客户端预校验这几个值,会直接把值打包成TDS请求发给SQL Server,SQL Server解析参数时发现值非法,就会抛出你看到的RPC协议流错误,报错里的参数序号(@p628)只是因为你待保存的实体字段多,参数排到了对应序号而已,和类型映射错误无关。
快速排查方法
在调用保存方法前加一段校验代码,扫出所有非法double值:
var invalidValues = dbContext.ChangeTracker.Entries() .Where(e => e.State is EntityState.Added or EntityState.Modified) .Select(e => e.Entity) .SelectMany(entity => entity.GetType().GetProperties() .Where(prop => prop.PropertyType == typeof(double)) .Select(prop => new { EntityType = entity.GetType().Name, PropertyName = prop.Name, InvalidValue = prop.GetValue(entity) }) .Where(x => double.IsNaN((double)x.InvalidValue) || double.IsInfinity((double)x.InvalidValue)) .ToList();
运行后如果invalidValues有数据,对应条目就是触发报错的字段,根据业务规则把这些特殊值替换为合法值(比如默认值0、可空类型赋值null)即可解决问题。
什么时候需要改数据类型
只有当你的业务场景明确需要存储NaN、无穷大这类特殊双精度值时,才需要调整映射:
- 方案1:将对应列类型改为
VARBINARY(8),存取时做double和字节数组的转换 - 方案2:将对应列改为字符串类型,序列化后存储
注意:不要盲目把实体属性从double改成decimal、或者把数据库列从float改成numeric/decimal,这类修改完全不对症,还会引入浮点数精度丢失的额外问题。
内容的提问来源于stack exchange,提问作者DanConsultant
相关产品推荐
相关产品推荐

