简体   繁体   中英

EF6 - Invalid cast from decimal to int32

I have some table with a field defined like...

...
[oneField] NUMERIC(2) NULL,
...

And the corresponding c# entity model...

...
public int? oneField { get; set; }
...

Fluent configuration...

Property(r => r.oneField)
    .HasColumnName("oneField");

Well, with all this above, I'm getting the following exception when retrieving data from the DB..

System.InvalidOperationException: The specified cast from a materialized
  'System.Decimal' type to a nullable 'System.Int32' type is not valid.

Any ideas to fix this? I could understand that if the NUMERIC field would have a decimal part that might cause the problem, but being just an integer value of 2 digits, why cannot be casted into an INT32?

Note: I know that if I change the field in the table to be an INT problem will be solved, but I'd like to keep the NUMERIC(2), as represents better the values that are to be stored there (Numbers with 2 digits).

If you want to use NUMERIC(2) then you need a decimal model property otherwise you will see the conversion errors that you report. So your solution is to change the database or change your model.

However, NUMERIC(2) is overkill for your purpose and will consume 5 bytes where you only want numbers up to 99. Instead you should consider using a TINYINT which will allow you to store numbers from 0 to 255. That would mean the storage is only a single byte and your model could be byte to match.

As far as I understand, it tells you that the column was materialized into a System.Decimal object and you're trying to cast it to a System.Int32 object which is not supported. Try using INTEGER to define your database column

Or alternatively using System.Decimal to define your EF object

Ok, if you want it, here is your model:

internal decimal? OneFieldIntenal { get; set; }
public int? OneField
{
    get => OneFieldIntenal.HasValue ? (int)OneFieldIntenal.Value : null;
    set => OneFieldIntenal = value;
}

Here is your mapping:

Property(r => r.OneFieldIntenal)
    .HasColumnName("oneField");

But only use this if you ABSOLUTELY sure what are you doing and you need to keep you type mismatch. This solution is ugly.

Assuming you are using sql server. Here are the .NET integer types and maximum fitting numeric types:

  • SByte => -128 to 127 which fits up to NUMERIC(2)
  • Int16 => -32,768 to 32,767 which fits up to NUMERIC(4)
  • Int32 => -2,147,483,648 to 2,147,483,647 which fits up to NUMERIC(9)
  • Int64 => -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 which fits up to NUMERIC(18)
  • decimal can hold up to 7.9*10^28 to NUMERIC(28) .

The problem is i doubt EF isnt going to like your conversion, since you are coding DB first and don't want to change anything, i think the only thing you can do is accept it for decimal and cast it client side.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM