private static void ConfigureEnumLookupTable(EntityTypeBuilder enumLookupBuilder, EnumLookupOptions enumOptions, Type enumType) { string typeName = enumType.Name; string tableName = enumOptions.NamingFunction(typeName); enumLookupBuilder.ToTable(tableName); }
// See https://github.com/aspnet/EntityFrameworkCore/issues/12248#issuecomment-395450990 public static void ConfigureEnumLookup(this ModelBuilder modelBuilder, EnumLookupOptions enumOptions) { foreach (IMutableProperty property in modelBuilder.Model.GetEntityTypes().SelectMany(x => x.GetProperties()).ToList()) { Type propertyType = property.ClrType; if (!propertyType.IsEnumOrNullableEnumType()) { continue; } if (enumOptions.UseEnumsWithAttributesOnly && !propertyType.HasEnumLookupAttribute()) { continue; } IMutableEntityType entityType = property.DeclaringEntityType; Dictionary <int, string> enumValueDescriptions = Enum.GetValues(propertyType.GetEnumOrNullableEnumType()) .Cast <Enum>() .ToDictionary(Convert.ToInt32, GetEnumDescription); bool usesDescription = enumValueDescriptions.Values.Any(x => x != null); Type concreteType; if (usesDescription) { concreteType = enumOptions.UseNumberLookup ? typeof(EnumWithNumberLookupAndDescription <>).MakeGenericType(propertyType.GetEnumOrNullableEnumType()) : typeof(EnumWithStringLookupAndDescription <>).MakeGenericType(propertyType.GetEnumOrNullableEnumType()); } else { concreteType = enumOptions.UseNumberLookup ? typeof(EnumWithNumberLookup <>).MakeGenericType(propertyType.GetEnumOrNullableEnumType()) : typeof(EnumWithStringLookup <>).MakeGenericType(propertyType.GetEnumOrNullableEnumType()); } EntityTypeBuilder enumLookupBuilder = modelBuilder.Entity(concreteType); string typeName = propertyType.GetEnumOrNullableEnumType().Name; string tableName = enumOptions.NamingFunction(typeName); enumLookupBuilder.ToTable(tableName); string keyName = enumOptions.UseNumberLookup ? nameof(EnumWithNumberLookup <Enum> .Id) : nameof(EnumWithStringLookup <Enum> .Id); modelBuilder.Entity(entityType.Name).HasOne(concreteType).WithMany().HasPrincipalKey(keyName).HasForeignKey(property.Name); if (enumOptions.UseNumberLookup) { modelBuilder.Entity(concreteType).HasIndex(nameof(EnumWithNumberLookup <Enum> .Name)).IsUnique(); } else { Type converterType = typeof(EnumToStringConverter <>).MakeGenericType(propertyType.GetEnumOrNullableEnumType()); ValueConverter valueConverter = (ValueConverter)Activator.CreateInstance(converterType, new object[] { null }); modelBuilder.Entity(entityType.Name).Property(property.Name).HasConversion(valueConverter); modelBuilder.Entity(concreteType).Property(keyName).HasConversion(valueConverter); } if (ConcreteTypeSeededList.Contains(concreteType)) { continue; } ConcreteTypeSeededList.Add(concreteType); // TODO: Check status of https://github.com/aspnet/EntityFrameworkCore/issues/12194 before using migrations object[] data = Enum.GetValues(propertyType.GetEnumOrNullableEnumType()) .OfType <object>() .Select(x => { object instance = Activator.CreateInstance(concreteType); if (enumOptions.UseNumberLookup) { concreteType.GetProperty(nameof(EnumWithNumberLookup <object> .Id)).SetValue(instance, x); concreteType.GetProperty(nameof(EnumWithNumberLookup <object> .Name)).SetValue(instance, x.ToString()); if (usesDescription) { concreteType.GetProperty(nameof(EnumWithNumberLookupAndDescription <object> .Description)) .SetValue(instance, enumValueDescriptions[(int)x]); } } else { concreteType.GetProperty(nameof(EnumWithStringLookup <object> .Id)).SetValue(instance, x); if (usesDescription) { concreteType.GetProperty(nameof(EnumWithNumberLookupAndDescription <object> .Description)) .SetValue(instance, enumValueDescriptions[(int)x]); } } return(instance); }) .ToArray(); enumLookupBuilder.HasData(data); } }