EF6 sembra essere incoerente nel modo in cui gestisce l'arrotondamento quando si moltiplicano e si aggiungono colonne di numeri interi con valori decimali.Arrotondamento decimale di Entity Framework incoerente nella proiezione
// 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();
Sicuramente questo non è il comportamento previsto/corretto? Mi aspetto che il valore di WithDecimals sia 50.5 (non 51). Sto trascurando qualcosa di semplice? Come posso garantire che WithoutDecimals non venga arrotondato senza modificare il tipo di altre costanti?
L'SQL generato per WithFloats e WithDecimals (rispettivamente):
,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
EF maps System.Decimal a DECIMAL (18, 0) per impostazione predefinita, quindi il valore di WithDecimals viene arrotondato al numero intero più vicino. Credo che ci sia un modo per modificare questo comportamento predefinito, per es. questo commento: http://stackoverflow.com/a/27418286/189572 – Max
@Max: l'aggiunta di una precisione decimale predefinita sembra non avere alcun effetto. Inoltre, se si aggiungesse un'altra colonna proiettata con l'espressione: (0.5m + row.MyIntValue) il risultato sarebbe 10.5, quindi il comportamento non sembrerebbe essere causato da una precisione decimale predefinita. – mindlessgoods
Interessante. Sembra che il cast di row.MyIntValue su DECIMAL (19,0) sia il problema, funziona con un cast su DECIMAL (18). Cosa succede quando lo passi in decimale in C#? '' 'WithDecimals = 0.5m + ((decimale) row.MyIntValue * 5.0m)' '' – Max