2015-12-23 46 views
7

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 
+0

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

+0

@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

+0

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

risposta

0

esplicitamente definire il tipo di colonna, nonché la precisione e la scala del campo decimale utilizzando un data-un'annotazione

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

È possibile trovare i mapping dei tipi CLR LINQ-to-SQL predefiniti, che si applicano quando si utilizza EF, here.

Lettura su tipi di dati numerici e decimali T-SQL here.