Dealing with Enumerations and Entity framework 4 – code first

UPDATE! There’s a June CTP with new support for enums!

If you have an entity with an enumeration and you wan’t to store it using Entity framework 4, Code-only, you might run into problem. The convention-based mapping is sufficent for generating the schema but you will run into problem when trying to create an objectset.

The solution that I will present here is kind of simple: Make a custom-type that you map as a complex-type using ComplexTypeConfiguration, then you implement implicit operator overloading to provide implicit-conversion between this custom-type and the enumeration.

The Entity

public class Tifi : ICamyinEntity
{
    public Guid Id { get; set; }

    public byte[] Version { get; set; }

    public TifiType Type { get; set; }

    public string Title { get; set; }

    public string Description { get; set; }

    public string Source { get; set; }
}

The Enumeration

public enum TifiTypes : int
{
    Undefined = 0,
    Blog = 1,
    Video = 2
}

The Custom-type

public class TifiType
{
    public int Value { get; private set; }

    private TifiType()
        : this(default(TifiTypes))
    {}

    public TifiType(int value)
    {
        Value = value;
    }

    public TifiType(TifiTypes type)
    {
        Value = (int)type;
    }

    public static implicit operator int(TifiType type)
    {
        return type.Value;
    }

    public static implicit operator TifiType(int value)
    {
        return new TifiType(value);
    }

    public static implicit operator TifiTypes(TifiType type)
    {
        return (TifiTypes)type.Value;
    }

    public static implicit operator TifiType(TifiTypes type)
    {
        return new TifiType(type);
    }
}

The Mappings

public class TifiTypeMapping : ComplexTypeConfiguration<TifiType>, ICamyinMapping
{
    public TifiTypeMapping()
    {
        Property(o => o.Value);
    }
}

public class TifiMapping : EntityConfiguration<Tifi>, ICamyinMapping
{
    public TifiMapping()
    {
        HasKey(o => o.Id);
        Property(o => o.Id)
            .StoreGeneratedPattern = StoreGeneratedPattern.Identity;

        Property(o => o.Version)
            .IsConcurrencyToken()
            .IsRequired()
            .HasStoreType("timestamp")
            .StoreGeneratedPattern = StoreGeneratedPattern.Computed;

        Property(o => o.Source)
            .HasMaxLength(200)
            .IsUnicode()
            .IsRequired();

        Property(o => o.Title)
            .HasMaxLength(100)
            .IsUnicode();

        Property(o => o.Description)
            .HasMaxLength(1000)
            .IsUnicode()
            .IsOptional();
    }
}

That’s it. You will now be able to assign enumeration values to an instance of Tifi and it’s member Type.

var tifi = new Tifi
{
    Title = "My first Tifi",
    Description = "This works",
    Source = "http://daniel.wertheim.se",
    Type = TifiTypes.Blog
};

//Daniel

About these ads

20 thoughts on “Dealing with Enumerations and Entity framework 4 – code first

  1. I’ve been using the string equivalent of this for a while now – the implementation is good and it means there won’t be much effort required to refactor once EF supports enums (EF12?).

    One point that might be worth noting is that you have to writes LINQ to Entities queries in a very specific way:


    var statusString = MyStatusEnum.Active.ToString();
    return enrolments.Where(x => x.Status.Value == statusString);

    This code will not work:


    return enrolments.Where(x => x.Status.Value == MyStatusEnum.Active);

    • That’s correct. You will have to use the Type.Value property in your queries. I would not compare it against the string, but instead the int representation. But that’s my opinion ;-)

      //Daniel

      • Hi Daniel,
        I get a unable to cast exception, when i do something like this

        var tifies = context.Tifies.where(t => t.Type == (int)TifiTypes.Blog).ToList();

        Am i doing it incorrectly?

        Thanks
        Guru

      • Please ignore my previous question. I was just being stupid by missing the t.Type.Value

        However, I want to store TifiTypes in a lookup table (for reporting purposes). And how can I add a foreign key on Type column pointing to the PK of the look up table using EF code first?

        Much appreciated.

        Thanks
        Guru

  2. Thanks for the article.

    I’ve been using ServiceResponse (Previous bits from core module) to get all result as well as any violations along with status code in the client. I see some changes in this release. I think you adopted IScenarioResponse and IScenarioRequest.

    Now I need to implement IScenarioRequest for any validation even string[] ???

    With ServiceResponse previous versions used “Try” action for executing data access layer. With new method how do you call similar functionality?

    Also in ServiceResponse I used to get all result as well as any violations along with status code but with new thing I forced to create a new class (for violations as well as result). Or am I doing something wrong here? Any code samples for the service layer to share?

  3. Thanks for the article, it’s just what I needed.
    Did I get it right that TifiMapping class doesn’t map TifiType explicitly? Will it’s ComplexTypeConfiguration be automatically picked up by EF4 or not?

  4. I tried it with EF 4.1 and it works like a charm

    One thing I did is decorating the class TifiType with [ComplexType] which in turn enabled me to remove the mapping TifiTypeMapping

    Thanks

  5. I added the property “Name” that returns the name of the enum as a string

    public class TifiType
    {
    public int Value { get; private set; }
    public string Name { get { return Enum.GetName(typeof(TifiTypes), Value); } }
    //—- The rest of the code
    }

  6. Why not:

    public class Tifi : ICamyinEntity
    {
    public Guid Id { get; set; }

    public int Type { get; set; }

    [NotMapped]
    public TifiTypes TifiType{
    get {return (TifiTypes)Type;}
    set {Type = (int)value;}
    }

    public string Title { get; set; }

    public string Description { get; set; }

    public string Source { get; set; }
    }


    var tifi = new Tifi
    {
    Title = “My first Tifi”,
    Description = “This works”,
    Source = “http://daniel.wertheim.se”,
    TifiType = TifiTypes.Blog
    };

    or I missing something?

    • Thanks for the comment and suggestion. Haven’t tested that but I guess you have and it’s cleaner seen to mappings but not to the model. Also it’s been a while since I wrote this and I don’t know what was supported when I tried it out.

      //Daniel

  7. This was a superb article, thank you.

    Though, since I wish to only implement the code once I have tried to make this a generic type that takes my enumtype as type in, ie public class EnumType but unfortunately that kind of implementation was not supported by EF 4.1.

    Instead I tried to make this a baseclass but ran into difficulties once again. Is there really no way to minimize the lines of code and still make this work?

    • I myself has tried to reuse mappings in earlier CTPs without any luck using inheritance and interfaces.

      //Daniel

  8. Pingback: SisoDb vs Entity Framework 4.1 Code first – Inserts « Daniel Wertheim

  9. The only problem for me is that I have to work on a legacy database that allows the field (type) to be null. This is the error I get:

    “The ‘Value’ property on ‘DocumentTypeWrapper’ could not be set to a ‘null’ value. You must set this property to a non-null value of type ‘Int32′.”

    Do you have any idea to how I can make it allow to be null? Or at lease how I can map the null value from the database to a default enum?

    • Hi,

      I guess you could do something like this:

      using System;
      
      namespace ConsoleApplication4
      {
          class Program
          {
              static void Main(string[] args)
              {
                  var t1 = new TifiType(null);
                  Console.WriteLine((TifiTypes)t1); //Writes Undefined
      
                  var t2 = new TifiType(1);
                  Console.WriteLine((TifiTypes)t2); //Writes Blog
      
                  Console.WriteLine(((TifiType)TifiTypes.Video).Value); //Writes 2
      
                  Console.ReadKey();
              }
          }
      
          public enum TifiTypes : int
          {
              Undefined = 0,
              Blog = 1,
              Video = 2
          }
      
      
          public class TifiType
          {
              public int? Value { get; private set; }
      
              private TifiType()
                  : this(default(TifiTypes))
              { }
      
              public TifiType(int? value)
              {
                  Value = value;
              }
      
              public TifiType(TifiTypes type)
              {
                  Value = (int)type;
              }
      
              public static implicit operator int(TifiType type)
              {
                  return type.Value ?? 0;
              }
      
              public static implicit operator TifiType(int value)
              {
                  return new TifiType(value);
              }
      
              public static implicit operator TifiTypes(TifiType type)
              {
                  return (TifiTypes)(type.Value ?? 0);
              }
      
              public static implicit operator TifiType(TifiTypes type)
              {
                  return new TifiType(type);
              }
          }
      
      }
      
    • I just figured out. I create a partial class of the complex type where I added the implicit operators. ;) thanks a bunch!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s