private static void ConfigureEnumLookupTable(EntityTypeBuilder enumLookupBuilder, EnumLookupOptions enumOptions, Type enumType)
        {
            string typeName  = enumType.Name;
            string tableName = enumOptions.NamingFunction(typeName);

            enumLookupBuilder.ToTable(tableName);
        }
예제 #2
0
        // 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);
            }
        }