Jasinski Technical Wiki

Navigation

Home Page
Index
All Pages

Quick Search
»
Advanced Search »

Contributor Links

Create a new Page
Administration
File Management
Login/Logout
Your Profile

Other Wiki Sections

Software

PoweredBy

Extension Method to Seed Enum Values into Database Table - Entity Framework Code First

RSS
Modified on Tue, Mar 24, 2020, 9:50 AM by Administrator Categorized as Entity Framework Code First

Overview

When an enum is persisted in a database table, it is better if the Code First entity doesn't use a (SQL Server) IDENTITY field. This is recommended for two reasons.

  • Having an IDENTITY field on an enum table requires the use of IDENTITY_INSERT, which Entity Framework doesn't play with well.
  • Changing from an IDENTITY field to a non-IDENTITY field is a troublesome endeavor in SQL Server. It requires the creation of a temporary table, the copying of data between tables, and a few table renames.

For these reasons, it is useful to have a base class to support the creation and seeding of enum tables in Entity Framework.

References

The AddSpaces extension method can be found here.

Reusable Code

Add this code within your DAL project/namespace.

public abstract class EnumDbEntity<TEnum>
{
    [Required]
    public TEnum Id { get; set; }

    [Required, StringLength(100)]
    public string Value { get; set; }

    /* TODO: Override this method where needed, especially if the derived class as extra fields. */
    public virtual EnumDbEntity<TEnum> InitForSeeding(TEnum value, bool addSpaces)
    {
        Id = value;
        Value = EnumHelper<TEnum>.GetDisplayValue(value, addSpaces);
        return this;
    }

}

public static class EnumDbEntityExtensions
{
    public static void SeedEnumTable<TEnum, TEntity>(this IDbSet<TEntity> dbSet)
        where TEnum : struct, IConvertible
        where TEntity : EnumDbEntity<TEnum>, new()
    {
        if (!typeof(TEnum).IsEnum) throw new ArgumentException("TEnum must be an enumerated type");

        var itemValues = (TEnum[])Enum.GetValues(typeof(TEnum));

        foreach (var itemValue in itemValues)
        {
            //dbSet.AddOrUpdate(a => a.Id, new TEntity { Id = itemValue, Value = EnumHelper<TEnum>.GetDisplayValue(itemValue) });
            var item = new TEntity();
            item.InitForSeeding(itemValue, addSpaces);
            dbSet.AddOrUpdate(a => a.Id, item);

        }

    }
}


/* Reference
    * https://stackoverflow.com/questions/13099834/how-to-get-the-display-name-attribute-of-an-enum-member-via-mvc-razor-code */
public static class EnumHelper<T>
    where T : struct, IConvertible
{

    public static string GetDisplayValue(T value)
    {
        var fieldInfo = value.GetType().GetField(value.ToString());

        var descriptionAttributes = fieldInfo.GetCustomAttributes(
            typeof(DisplayAttribute), false) as DisplayAttribute[];

        //if (descriptionAttributes[0].ResourceType != null)
        //    return lookupResource(descriptionAttributes[0].ResourceType, descriptionAttributes[0].Name);

        if (descriptionAttributes == null) return string.Empty;
        return (descriptionAttributes.Length > 0) ? descriptionAttributes[0].Name : value.ToString().AddSpaces();
    }
}

Implementation Sample Code

Enum and Database Entity

public enum OrderStatusEnum
{
    Active,
    Inactive
}

public class OrderStatus : EnumDbEntity<OrderStatusEnum>
{ }

Seeding the Table

context.OrderStatuses.SeedEnumTable<OrderStatusEnum, OrderStatus>();

ScrewTurn Wiki version 3.0.1.400. Some of the icons created by FamFamFam. Except where noted, all contents Copyright © 1999-2020, Patrick Jasinski.