I’m working on a side project where I use Entity Framework 6 for my data layer. I need to store an enum in the database as string rather than integer. This is because I don’t like having enum columns in database without meaningful value. Plus this also makes it easier to know what that enum value is when viewing data from SSMS or on report and removes the need to look up its equivalent text value in the query. It is just a personal preference.
However, Entity Framework 6 does not support this. There is this popular workaround where a new property for the string version of the enum is added to the class with the Column attribute. In the get accessor, return the ToString() method of the enum property. In the set accessor, make it private and parse the value to the enum property. Then mark the current enum property with NotMapped attribute so that it will be ignored when deploying/updating the database. For example,
public enum EmploymentStatus { Unemployed = 1, Fulltime = 2, Parttime = 3 } public class BackgroundDetail { public int UserId { get; set; } [Colum("EmploymentStatus")] public string EmploymentStatusString { get { return this.EmploymentStatus.ToString(); } set { this.EmploymentStatus = Enum.Parse(typeof(EmploymentStatus), value, true); } } [NotMapped] public EmploymentStatus EmploymentStatus { get; set; } }
Now I have 3 issues with that option.
- It is not clean. It might be ok if there is only one enum property in the model. This can get really messy when you have 2 or more enum properties in your model.
- In terms of separation of concern, this highly couples the model with the framework/technology for the data layer. The models should not have to workaround the data layer due to some limitations in the technology used in the data layer.
My solution to this issue is using static class with constant string fields as enum.
public static class EmploymentStatus { public const string Unemployed = "Unemployed"; public const string Fulltime = "Fulltime"; public const string Parttime = "Parttime"; } public class BackgroundDetail { public int UserId { get; set; } public string EmploymentStatus { get; set; } }
I’ve used this kind of class before but for a different purpose, as a class containing text for menu items. The benefit of this solution is that you won’t need any additional string property per enum property. Another benefit of this solution is that, if in the future you decide to change the database technology to something else that support enum as text when storing in the database, it reduces number of changes in the code.
This solution however still requires to modify the model to accommodate limitations in the database technology, though less changes required compared to the solution above. The property type has to be string instead of the name of the ‘enum’.
You should have business logic in your application to validate what can go into the database table. You can also add constraint on the table too however I think that is business logic and should let the app handle it.
With your solution I can set EmploymentStatus to “ToiletCleaner”.
There is no enforcement of the data values !
That popular solution you mention has another (big) drawback:
when you use the not-mapped property in a where -statement, this will not be propagated to the SQL statement, but that filter will be done in memory!
Thanks for some other fantastic post. The place else may anyone get that kind of info in such a perfect means of writing? I have a presentation next week, and I am on the look for such info.
Admiring the time and energy you put into your blog and detailed information you
provide. It’s awesome to come across a blog every once in a while that isn’t the same outdated rehashed information.
Wonderful read! I’ve bookmarked your site and I’m adding your RSS feeds
to my Google account.