SQL Server в .Net Десятичные числа с EF6 dDatabase первый выпуск - PullRequest
4 голосов
/ 09 мая 2019

Я сейчас читаю данные из хранимой процедуры SQL Server, и она возвращается как Decimal(38, 20).

Я знаю, что десятичное число .Net равно (28, 10), но классы моделей, сгенерированные для этого EF, показывают Decimal?. Когда я запрашиваю таблицу, код выдает ошибку переполнения преобразования, потому что он пытается поместить десятичный разряд SQL Server в десятичное поле .Net.

Есть ли простой способ преобразовать его в .Net десятичный через контекст данных? По сути, у меня нет доступа для изменения типа данных SQL Server.

Тип данных SQL Server:

 Amount Decimal(38, 20)

Entity

public class EntityClass
{
     public decimal? Amount { get; set; }
}

И когда я звоню

 var eee =  _context.EntityClass
                    .Select(x => x.Amount)
                    .FirstOrDefaultAsync();

Я получаю

Ошибка переполнения конверсии

Ответы [ 2 ]

0 голосов
/ 10 мая 2019

Это ошибка или ограничение в .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

0 голосов
/ 10 мая 2019

в вашем ApplicationDbContext вы должны добавить

  protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
        builder.Entity<EntityClass>()
            .Property(p => p.Amount )
            .HasColumnType("decimal(28,20)");
...