SQL Server to .Net Decimals with EF6 database first issue
Posted
技术标签:
【中文标题】SQL Server to .Net Decimals with EF6 database first issue【英文标题】:SQL Server to .Net Decimals with EF6 dDatabase first issue 【发布时间】:2019-09-27 15:55:43 【问题描述】:我目前正在从 SQL Server 存储过程中读取数据,它返回为 Decimal(38, 20)
。
我知道 .Net 小数点是 (28, 10)
,但 EF 为此生成的模型类显示 Decimal?
。当我查询表时,代码会引发转换溢出错误,因为它试图将 SQL Server 小数点放在 .Net 小数点字段中。
有没有一种简单的方法可以通过数据上下文将其转换为 .Net 十进制?基本上我无权修改 SQL Server 数据类型。
SQL Server 数据类型:
Amount Decimal(38, 20)
实体
public class EntityClass
public decimal? Amount get; set;
当我打电话时
var eee = _context.EntityClass
.Select(x => x.Amount)
.FirstOrDefaultAsync();
我明白了
转换溢出错误
【问题讨论】:
什么版本的 EF?您需要保留多少个有效数字?数据库中的什么值导致溢出? 这个肯定是个问题 (-4210862852.86000000000000000000)。 是的。我可以重现。什么版本的 EF? 为什么你不在课堂上使用 double ?公双?金额得到;放; @YairI double 不是just
,它会让事情变得更糟。它的范围比 Decimal 小 并且保证会导致舍入错误。它也不会影响这个错误 - 字段的范围太长了
【参考方案1】:
这是 .NET 的 SqlClient 的错误或限制。这是一个再现:
using (var con = new SqlConnection("server=.;database=tempdb;Integrated Security=true"))
con.Open();
var cmd = new SqlCommand("select cast(4210862852.86 as decimal(38,20)) val", con);
using (SqlDataReader rdr = cmd.ExecuteReader())
rdr.Read();
var val = rdr.GetDecimal(0);
Console.WriteLine(val);
问题是这个数字
select cast(cast(4210862852.86 as decimal(38,20)) as varbinary(20))
被存储,并通过网络传输
0x261400010000D877FB4DEE8B51699A5005000000
而且 SqlClient 将拒绝转换最后 4 个字节中任何非零的小数:
internal decimal Decimal
get
ThrowIfNull();
if (StorageType.Decimal == _type)
if (_value._numericInfo.data4 != 0 || _value._numericInfo.scale > 28)
throw new OverflowException(SQLResource.ConversionOverflowMessage);
return new decimal(_value._numericInfo.data1, _value._numericInfo.data2, _value._numericInfo.data3, !_value._numericInfo.positive, _value._numericInfo.scale);
if (StorageType.Money == _type)
long l = _value._int64;
bool isNegative = false;
if (l < 0)
isNegative = true;
l = -l;
return new decimal((int)(l & 0xffffffff), (int)(l >> 32), 0, isNegative, 4);
return (decimal)this.Value; // anything else we haven't thought of goes through boxing.
https://github.com/dotnet/corefx/blob/master/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlBuffer.cs
我在这里打开了一个针对 .NET Core 的问题:https://github.com/dotnet/corefx/issues/37592
【讨论】:
【参考方案2】:您应该在 ApplicationDbContext 中添加
protected override void OnModelCreating(ModelBuilder builder)
base.OnModelCreating(builder);
builder.Entity<EntityClass>()
.Property(p => p.Amount )
.HasColumnType("decimal(28,20)");
【讨论】:
“我无权修改 SQL Server 数据类型” OP的问题是数据库字段的精度38。Decimal
最多可以处理 28 个。HasColumnType("decimal(28,20)")
也不会更改现有字段的精度,因此不会影响可以在那里存储的值。以上是关于SQL Server to .Net Decimals with EF6 database first issue的主要内容,如果未能解决你的问题,请参考以下文章
HOW TO CHECK FOR ACTIVE TRACE FLAGS ON MICROSOFT SQL SERVER
翻译:Stairway to SQL Server Replication: Level 1 - Introduction to SQL Server Replication
Stairway to SQL Server Replication: Level 1 - Introduction to SQL Server Replication翻译,合并截图翻译
SSMS 远程连接SERVER 设置 - Unable to connect to SQL Server instance remotely