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

Advertisement
Tagged , ,

18 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);

    • Daniel Wertheim says:

      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

      • Guru says:

        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

      • Guru says:

        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. Ashraf says:

    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. Gleb says:

    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. Korayem says:

    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. Korayem says:

    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. Alexey says:

    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?

    • Daniel Wertheim says:

      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. Per says:

    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?

    • Daniel Wertheim says:

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

      //Daniel

  8. [...] note that EF will not handle the enumeration in the model above. There are ways to get around this problem, but that’s not what this post is [...]

  9. Niels Peter Gibe says:

    I am aware, that there has been an update to EF, so that it now supports Enums. On the ADO.NET team blog, there is walkthrough, explaining the use of Enums with ModelFirst/Database first tools (http://blogs.msdn.com/b/adonet/archive/2011/06/30/walkthrough-enums-june-ctp.aspx).

    What I need to learn, is how to implement it it via Code First. Does anyone here have any information about that?

  10. Vegard says:

    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?

    • Daniel Wertheim says:

      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);
              }
          }
      
      }
      

Leave a Reply

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

Gravatar
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 )

Connecting to %s

Follow

Get every new post delivered to your Inbox.