using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using iPackage.Models.Entity; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata; using Pluralize.NET; namespace iPackage.Core.Web.Extensions { public class ModelBuilderQueryFilter { public void AddQueryFilterToModelBuilder(ModelBuilder modelBuilder, Type type) { MethodInfo method = this.GetType().GetMethod("RegisterQueryFilter").MakeGenericMethod(type); method.Invoke(this, new object[] { modelBuilder }); } public void RegisterQueryFilter(ModelBuilder modelBuilder) where TQFilter : ApiEntity { Type tt = typeof(TQFilter); if (tt.BaseType == typeof(ApiEntity)) modelBuilder.Entity().HasQueryFilter(e => e.IsRemoved == false); } } public static class ModelBuilderExtensions { /// /// Singularizin table name like Posts to Post or People to Person /// /// public static void AddSingularizingTableNameConvention(this ModelBuilder modelBuilder) { Pluralizer pluralizer = new Pluralizer(); foreach (IMutableEntityType entityType in modelBuilder.Model.GetEntityTypes()) { string tableName = entityType.GetTableName(); entityType.SetTableName(pluralizer.Singularize(tableName)); } } /// /// Pluralizing table name like Post to Posts or Person to People /// /// public static void AddPluralizingTableNameConvention(this ModelBuilder modelBuilder) { Pluralizer pluralizer = new Pluralizer(); foreach (IMutableEntityType entityType in modelBuilder.Model.GetEntityTypes()) { if (entityType.BaseType == null) { string tableName = entityType.GetTableName(); entityType.SetTableName(pluralizer.Pluralize(tableName)); } } } /// /// Set NEWSEQUENTIALID() sql function for all columns named "Id" /// /// /// Set to true if you want only "Identity" guid fields that named "Id" public static void AddSequentialGuidForIdConvention(this ModelBuilder modelBuilder) { modelBuilder.AddDefaultValueSqlConvention("Id", typeof(Guid), "NEWSEQUENTIALID()"); } /// /// Set DefaultValueSql for sepecific property name and type /// /// /// Name of property wants to set DefaultValueSql for /// Type of property wants to set DefaultValueSql for /// DefaultValueSql like "NEWSEQUENTIALID()" public static void AddDefaultValueSqlConvention(this ModelBuilder modelBuilder, string propertyName, Type propertyType, string defaultValueSql) { foreach (IMutableEntityType entityType in modelBuilder.Model.GetEntityTypes()) { IMutableProperty property = entityType.GetProperties().SingleOrDefault(p => p.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase)); if (property != null && property.ClrType == propertyType) property.SetDefaultValueSql(defaultValueSql); } } /// /// Set DeleteBehavior.Restrict by default for relations /// /// public static void AddRestrictDeleteBehaviorConvention(this ModelBuilder modelBuilder) { IEnumerable cascadeFKs = modelBuilder.Model.GetEntityTypes() .SelectMany(t => t.GetForeignKeys()) .Where(fk => !fk.IsOwnership && fk.DeleteBehavior == DeleteBehavior.Cascade); foreach (IMutableForeignKey fk in cascadeFKs) fk.DeleteBehavior = DeleteBehavior.Restrict; } /// /// Dynamicaly load all IEntityTypeConfiguration with Reflection /// /// /// Assemblies contains Entities public static void RegisterEntityTypeConfiguration(this ModelBuilder modelBuilder, params Assembly[] assemblies) { MethodInfo applyGenericMethod = typeof(ModelBuilder).GetMethods().First(m => m.Name == nameof(ModelBuilder.ApplyConfiguration)); IEnumerable types = assemblies.SelectMany(a => a.GetExportedTypes()) .Where(c => c.IsClass && !c.IsAbstract && c.IsPublic); foreach (Type type in types) { foreach (Type iface in type.GetInterfaces()) { if (iface.IsConstructedGenericType && iface.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>)) { MethodInfo applyConcreteMethod = applyGenericMethod.MakeGenericMethod(iface.GenericTypeArguments[0]); applyConcreteMethod.Invoke(modelBuilder, new object[] { Activator.CreateInstance(type) }); } } } } /// /// Dynamicaly register all Entities that inherit from specific BaseType /// /// /// Base type that Entities inherit from this /// Assemblies contains Entities public static void RegisterAllEntities(this ModelBuilder modelBuilder, params Assembly[] assemblies) where BaseType : ApiEntity { IEnumerable types = assemblies.SelectMany(a => a.GetExportedTypes()) .Where(c => c.IsClass && !c.IsAbstract && c.IsPublic && typeof(BaseType).IsAssignableFrom(c)); ModelBuilderQueryFilter builderQueryFilter = new ModelBuilderQueryFilter(); Pluralizer pluralizer = new Pluralizer(); foreach (Type type in types) { modelBuilder.Entity(type); builderQueryFilter.AddQueryFilterToModelBuilder(modelBuilder, type); } } } }