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

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

Compare Page Revisions



« Older Revision - Back to Page History - Newer Revision »


Page Revision: Thu, May 28, 2020, 4:38 PM


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>
        where TEnum : struct, IConvertible
{
    [Required]
    public TEnum Id { get; set; }

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

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

}

public static class EnumDbEntityExtensions
{
    public static void SeedEnumTable<TEnum, TEntity>(this IDbSet<TEntity> dbSet, bool addSpaces = true)
        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)
        {
            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, bool addSpaces = true)
    {
        var ret = String.Empty;
        var fieldInfo = value.GetType().GetField(value.ToString());

        if (fieldInfo == null)
        {
            return "Display Name Unknown";
        }

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

        if (dispAttrib != null)
        {
            if (dispAttrib.Length > 0)
            {
                ret = dispAttrib[0].Name;
            }
            else
            {
                ret = value.ToString();

                if (addSpaces)
                {
                    ret = ret.AddSpaces();
                }
            }
        }
        return ret;
    }
}

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-2024, Patrick Jasinski.