Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nullable enum field with Code First Approach doesn't create the enum Field in Database

I am using the code first approach to create the schema and then populating the data in it with the help of Seed method

I am using Entity Framework Version 5.0,SQLEXPRESS2008 and MVC4

below is my Model

  public enum Grade
{
    A, B, C, D, F
}

public class Enrollment
{
    public int EnrollmentID { get; set; }
    public int CourseID { get; set; }
    public int StudentID { get; set; }
    [DisplayFormat(NullDisplayText = "No grade")]
    public Grade? Grade { get; set; }
    public virtual Course Course { get; set; }
    public virtual Student Student { get; set; }
}

this is how i populate the data to the Database using seed method in Intializer

 var enrollments = new List<Enrollment>
        {
        new Enrollment{StudentID=1,CourseID=1050,Grade=Grade.A},
        new Enrollment{StudentID=1,CourseID=4022,Grade=Grade.C},
        new Enrollment{StudentID=1,CourseID=4041,Grade=Grade.B},
        new Enrollment{StudentID=2,CourseID=1045,Grade=Grade.B},
        new Enrollment{StudentID=2,CourseID=3141,Grade=Grade.F},
        new Enrollment{StudentID=2,CourseID=2021,Grade=Grade.F},
        new Enrollment{StudentID=3,CourseID=1050},
        new Enrollment{StudentID=4,CourseID=1050,},
        new Enrollment{StudentID=4,CourseID=4022,Grade=Grade.F},
        new Enrollment{StudentID=5,CourseID=4041,Grade=Grade.C},
        new Enrollment{StudentID=6,CourseID=1045},
        new Enrollment{StudentID=7,CourseID=3141,Grade=Grade.A},
        };
        enrollments.ForEach(s => context.Enrollments.Add(s));
        context.SaveChanges();

on debug ,I am able to see the data in "Grade" Column within that context

but it neither creates the Column "Grade" in Database nor populates its data.

I have setup the Context and Database Initalizer as below in my web.config

   <entityFramework>
  <context type="EntityFrameworkWithMVC.DAL.SchoolContext, EntityFrameworkWithMVC">
    <databaseInitializer type="EntityFrameworkWithMVC.DAL.SchoolInitializer,  EntityFrameworkWithMVC" />
    </context>
   </contexts>
  </entityFramework>
like image 302
Harshil Gandhi Avatar asked Jun 27 '26 01:06

Harshil Gandhi


1 Answers

You will need .NET 4.5

Enum support is not available in EF 5 with .NET 4.0. This is due to a change in System.Data.Entity which is located not in the EF 5 library but in the .NET 4.5 version.

See: http://social.msdn.microsoft.com/Forums/en-US/55dc58a4-6190-4bad-b317-1787cf86bf3d/ef-5-but-no-enum-support?forum=adodotnetentityframework

Are there technical reasons EF 5 isn't fully supported on .NET4.0?

You'll need a workaround to extract your enum value (you can use int and convert to enum in your mappings) or upgrade to .NET 4.5

[UPDATE] As for a workaround, there are a couple of options, In all cases you'll need to write your enum value as a string or int (or other supported type) to the database:

  • Use a mapper

If you are using a ViewModel or something similar you can implement a configurable mapper like AutoFac (http://www.nuget.org/packages/Autofac/). It's a bit hard to use at first but it has all the features for IOC, MVC etc. You can define a custom mapping definition so that you can use the enum in your ViewModel and the int value in your entity. The custom mapping contains the conversion from int to enum and back.

  • Use a [NotMapped] column

This is faster to implement, but it usually bites you in the tail:

public int? GradeValue {get;set;}

[NotMapped]
[DisplayFormat(NullDisplayText = "No grade")]
public Grade? Grade 
{ 
    get 
    { 
         return GradeValue.HasValue ? (Grade?) GradeValue.Value : null; 
    } 
}

The [NotMapped] attribute ensures the enum is not added to the database (might come in handy if you'll decide to upgrade to .NET 4.5 later on).

Now you can read the value as an enum. My guess is that GradeValue needs to be public (private/protected would give you some advantages) (not sure if supported in this version). If it has to be public; its kind of tricky because other developers might use this GradeValue directly.

Alternatively you can do something similar for the set instruction.

Hope this helps.

like image 50
Stefan Avatar answered Jun 28 '26 17:06

Stefan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!