2015-12-23 10 views
7

EF6 wydaje się być niekonsekwentny w sposobie obsługi zaokrąglania podczas mnożenia i dodawania kolumn całkowitych z wartościami dziesiętnymi.Entity Framework zaokrąglanie dziesiętne niespójne w projekcji

// CREATE TABLE MyTable (MyIntValue INT NOT NULL) 
// INSERT INTO MyTable (MyIntValue) VALUES (10) 
const int IntScale = 5; 
const decimal DecimalScale = 5; 
const decimal DecimalScale2 = 5.0m; 
context.Set<MyTable>() 
    .Select(row => new 
    { 
     WithFloats = 0.5f + (row.MyIntValue * 5.0f),       // 50.5 
     WithDecimals = 0.5m + (row.MyIntValue * 5.0m),      // 51 
     WithDecimals2 = 0.5m + ((decimal)row.MyIntValue * 5.0m),    // 50.5    
     WithDecimals3 = 0.5m + ((decimal)row.MyIntValue * IntScale),   // 51 
     WithDecimals4 = 0.5m + ((decimal)row.MyIntValue * (decimal)IntScale) // 51 
     WithDecimals5 = 0.5m + ((decimal)row.MyIntValue * DecimalScale)  // 51 
     WithDecimals6 = 0.5m + ((decimal)row.MyIntValue * DecimalScale2)  // 50.5 
    }) 
    .Single(); 

Z pewnością nie jest to oczekiwane/prawidłowe zachowanie? Oczekuję, że wartość WithDecimals będzie wynosiła 50,5 (nie 51). Czy przeoczyłem coś prostego? W jaki sposób mogę zagwarantować, że metoda WithoutDecimals nie zostanie zaokrąglona bez zmiany typu pozostałych stałych?

Wytworzona SQL dla WithFloats i WithDecimals (odpowiednio):

,CAST(0.5 AS REAL) + (CAST(MyIntValue AS REAL) * CAST(5 AS REAL)) AS WithFloats 
,0.5 + (CAST(MyIntValue AS DECIMAL(19,0)) * CAST(5 AS DECIMAL(18))) AS WithDecimals 
+0

EF mapy System.Decimal do DECIMAL (18, 0) domyślnie, więc twoja wartość WithDecimals zostanie zaokrąglona do najbliższej liczby całkowitej. Wierzę, że istnieje sposób na zmianę tego domyślnego zachowania, zobacz np. ten komentarz: http://stackoverflow.com/a/27418286/189572 – Max

+0

@Max: Dodanie domyślnej dokładności dziesiętnej wydaje się nie mieć żadnego efektu. Co więcej, gdyby dodać kolejną rzutowaną kolumnę z wyrażeniem: (0,5 m + wiersz.MójIntWartość), wynik będzie wynosił 10,5, więc zachowanie nie wydaje się być spowodowane domyślną dokładnością dziesiętną. – mindlessgoods

+0

Interesujące. Wygląda jak obsada wiersza.MyIntValue na DECIMAL (19,0) jest problemem, działa z rzutowaniem na DECIMAL (18). Co stanie się, gdy rzucisz go w systemie C# w systemie dziesiętnym? '' 'WithDecimals = 0.5m + ((dziesiętny) wiersz.MyIntValue * 5.0m)' '' – Max

Odpowiedz

0

określić rodzaj kolumny, jak również dokładność i rozmiar pola przecinku przy użyciu danych-adnotacji

[Column(TypeName = "decimal(5,2)")] 
public decimal MyDecimal { get; set; } 

Można znaleźć domyślne odwzorowania typu CLR typu LINQ-SQL, które ma zastosowanie w przypadku EF, here.

Czytaj na temat numerycznych i dziesiętnych typów danych T-SQL here.