Unchecked, ulong & Entity Framework

Hej! Chwilę nie pisałem, ale to chyba jest tak, że w życiu mam wiele innych priorytetów i przez zimę ciężko mi się zebrać. Tym bardziej, że były sezon snowboardowy był najlepszym dotychczas w moim życiu i udało mi się spędzić 35 dni na stoku i raz wylądować w szpitalu, całe szczęście nic się nie stało :).

Przejde do rzeczy, zacznę od słówka kluczowego unchecked, którego nie miałem jeszcze do niedawna okazji użyć. Unchecked używamy wtedy kiedy chcemy zapobiec overflow exception podczas runtime’u. W moim przypadku musiałem się zabezpieczyć przy konwertowaniu wartości ulong na long. Dlaczego? Wg. założeń biznesowych i osób ode mnie mądrzejszych zostało postanowione, że wartości ID będziemy trzymać w danych typu ulong. (Dla ciekawskich różnica między nimi jest taka, że w typach unsigned jak np. ulong nie trzymamy znaku wartości i są one tylko i wyłącznie dodatnie. W typach np. long na 1 bicie przetrzymujemy informacje o tym czy jest to dodatnia czy ujemna liczba)

Problem pojawił się przy wsparciu Entity Frameworka, mssql nie obsługuje typu ulong w bazie a EF sam w sobie nie był w stanie rzutować tych danych. Nie jest to wielkie programistyczne wyzwanie, wystarczy stworzyć ignorowane przez EF pole, które będzie konwertować nam wartość na typ ulong. Na zewnątrz chcemy mieć wartość ulong, w bazie natomiast przetrzymywać longa.

Nic prostszego, przejdźmy więc do kodu! 🙂

Klasa bazowa (normalnie zawiera troszkę więcej danych ale na rzecz tego wpisu skróciłem strukturę do minimum):

public abstract class Entity
{
    public virtual ulong Id { get; set; }
    internal virtual long ID
    {
        get
        {unchecked{return (long)Id;}}
        set
        {unchecked{Id = (ulong)value;}}
    }
}

Przykładowa klasa, która dziedziczy po naszej bazie

    public class AccountingTransaction : Entity
    {
      //other propeties
    }

Konfiguracja dla .NET 4.6.1:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Types<AccountingTransaction>()
                    .Configure(c => c.Ignore(x => x.Id));
    modelBuilder.Entity<AccountingTransaction>()
                    .Property(x => x.ID)
                    .IsRequired()
                    .HasColumnName("ID");

    modelBuilder.Entity<AccountingTransaction>()
                    .HasKey(x => x.ID);
}  

Jako, że w projekcie miałem wesprzeć dwa frameworki (.NET Standard 2.0 oraz .NET 4.6.1), to konfiguracja dla .NET Standard 2.0 wygląda tak:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<AccountingTransaction>().Ignore(x => x.Id);
    modelBuilder.Entity<AccountingTransaction>()
                    .HasKey(x => x.ID)
                    .HasName("ID");
}  

Wszystko super tylko kod ten działa w wersji .NET Standard 2.0, jednak dla starego .NET Framework 4.6.1 oraz EF 6.2 już nie 🙂 Kod się kompiluje jednak podczas materializacji tabeli, wyrzuca błąd:

System.InvalidOperationException Message=The key component ‚ID’ is not a declared property on type ‚AccountingTransaction’. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property.

Problem rozwiązuje się, gdy usuniemy bazową klasę Entity i mapowanie ID przeniesiemy bezpośrednio do klasy AccountingTransaction. Jednak wg. mnie nie jest to dobre rozwiązanie w przypadku gdy mamy wiele encji.

Jak to rozwiązać? Jeszcze do tego nie doszedłem ale stwierdziłem, że jest to na tyle mało spotykana sytuacja, że warto o tym napisać :). Może Ty masz jakiś pomysł? Zapraszam do dyskusji i „rzucania pomysłów”.

Na koniec standardowo piosenka 🙂

Reklamy

3 myśli w temacie “Unchecked, ulong & Entity Framework

  1. Pingback: dotnetomaniak.pl

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj /  Zmień )

Zdjęcie na Google+

Komentujesz korzystając z konta Google+. Wyloguj /  Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj /  Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj /  Zmień )

w

Connecting to %s