33

Class properties with the long data type are properly mapped when adding a new migration (code-first), but ulong data types are skipped by mysql's EF provider. How does one map a property to use mysql's unsigned bigint?

arao6
  • 3,316
  • 5
  • 30
  • 51

2 Answers2

57

Update Feb 2021

Apparently EF Core now supports ulong -- see @JimbobTheSailor's answer below.


Older Entity Framework versions:

Turns out that Entity Framework does not support unsigned data types. For uint columns, one could just store the value in a signed data type with a larger range (that is, a long). What about ulong columns? The common solution couldn't work for me because there is no EF-supported signed data type that can hold a ulong without overflowing.

After a bit of thinking, I figured out a simple solution to this problem: just store the data in the supported long type and cast it to ulong when accessed. You might be thinking: "But wait, ulong's max value > long's max value!" You can still store the bytes of a ulong in a long and then cast it back to ulong when you need it, since both have 8 bytes. This will allow you to save a ulong variable to a database through EF.

// Avoid modifying the following directly.
// Used as a database column only.
public long __MyVariable { get; set; }

// Access/modify this variable instead.
// Tell EF not to map this field to a Db table
[NotMapped]
public ulong MyVariable
{
    get
    {
        unchecked
        {
            return (ulong)__MyVariable;
        }
    }

    set
    {
        unchecked
        {
            __MyVariable = (long)value;
        }
    }
}

The casting is unchecked to prevent overflow exceptions.

Hope this helps someone.

arao6
  • 3,316
  • 5
  • 30
  • 51
  • 2
    What if you are trying to work with numbers larger than a long? – Douglas Gaskell Feb 04 '17 at 20:18
  • +1 keyword unchecked. But, why would you be editing at the level of where your auto-generated POCO entities reside such as in EF model first? If you extend them by deriving a new class and type referencing the base property, it is no different than type conversion at this point and your POCOs remain in tact. Arithmetic overflow may be ignored but the result is still truncated. – Latency Mar 13 '18 at 15:12
  • @DouglasGaskell: You work wih the numbers as an `ulong`. You only _store_ them as a `long`. They won't make sense in their `long` version but that doesn't matter since they will always convert back to the precise `ulong` value they used to be, which means you just have to cast them back when you want to use them. However, you can't do in-database calculations as they will use the 'bad' long value. – Flater Jul 13 '20 at 00:28
8

Update Entity Framework Core Feb 2021

EF Core 3.1: EF Core now supports long and ulong types. Using code first, the long or ulong is mapped to EF Core's new 'Decimal Type'

public ulong MyULong{ get; set; } //==> decimal(20, 0)

A ulong results in a decimal being defined in the database with 20 digits and 0 digits to the right of the decimal point, which is sufficient to store a 64 bit ulong.

EF 5: Thankyou to @Tomasz for noting that in EF 5 and 6 the ulong is mapped to a BigInt, rather than the Decimal type as per my original answer, now under the heading "EF Core 3.1" above

JimbobTheSailor
  • 1,441
  • 1
  • 12
  • 21
  • Which version are you using? I have tried 6.0.0 (preview) and 5.0.3, and both versions generating `Test = table.Column(type: "bigint", nullable: false),` from `public ulong Test { get; set; }` – Tomasz Feb 20 '21 at 21:07
  • 1
    Hi @Tomasz I'm using EF Core 3.1. It appears that the mapping to decimal has been updated to map to 'bigint' in later versions, as you have pointed out – JimbobTheSailor Feb 20 '21 at 21:44
  • 1
    6.0.0-preview.2.21154.2 and 5.0.4 are both generating table.Column(type: "decimal(20,0)", nullable: false) for me – Stewart Cunningham Mar 26 '21 at 15:28