iPackage/iPackage.Core.Web/Extensions/ModelBuilderExtensions.cs

148 lines
6.6 KiB
C#

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<TQFilter>(ModelBuilder modelBuilder) where TQFilter : ApiEntity
{
Type tt = typeof(TQFilter);
if (tt.BaseType == typeof(ApiEntity))
modelBuilder.Entity<TQFilter>().HasQueryFilter(e => e.IsRemoved == false);
}
}
public static class ModelBuilderExtensions
{
/// <summary>
/// Singularizin table name like Posts to Post or People to Person
/// </summary>
/// <param name="modelBuilder"></param>
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));
}
}
/// <summary>
/// Pluralizing table name like Post to Posts or Person to People
/// </summary>
/// <param name="modelBuilder"></param>
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));
}
}
}
/// <summary>
/// Set NEWSEQUENTIALID() sql function for all columns named "Id"
/// </summary>
/// <param name="modelBuilder"></param>
/// <param name="mustBeIdentity">Set to true if you want only "Identity" guid fields that named "Id"</param>
public static void AddSequentialGuidForIdConvention(this ModelBuilder modelBuilder)
{
modelBuilder.AddDefaultValueSqlConvention("Id", typeof(Guid), "NEWSEQUENTIALID()");
}
/// <summary>
/// Set DefaultValueSql for sepecific property name and type
/// </summary>
/// <param name="modelBuilder"></param>
/// <param name="propertyName">Name of property wants to set DefaultValueSql for</param>
/// <param name="propertyType">Type of property wants to set DefaultValueSql for </param>
/// <param name="defaultValueSql">DefaultValueSql like "NEWSEQUENTIALID()"</param>
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);
}
}
/// <summary>
/// Set DeleteBehavior.Restrict by default for relations
/// </summary>
/// <param name="modelBuilder"></param>
public static void AddRestrictDeleteBehaviorConvention(this ModelBuilder modelBuilder)
{
IEnumerable<IMutableForeignKey> 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;
}
/// <summary>
/// Dynamicaly load all IEntityTypeConfiguration with Reflection
/// </summary>
/// <param name="modelBuilder"></param>
/// <param name="assemblies">Assemblies contains Entities</param>
public static void RegisterEntityTypeConfiguration(this ModelBuilder modelBuilder, params Assembly[] assemblies)
{
MethodInfo applyGenericMethod = typeof(ModelBuilder).GetMethods().First(m => m.Name == nameof(ModelBuilder.ApplyConfiguration));
IEnumerable<Type> 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) });
}
}
}
}
/// <summary>
/// Dynamicaly register all Entities that inherit from specific BaseType
/// </summary>
/// <param name="modelBuilder"></param>
/// <param name="baseType">Base type that Entities inherit from this</param>
/// <param name="assemblies">Assemblies contains Entities</param>
public static void RegisterAllEntities<BaseType>(this ModelBuilder modelBuilder, params Assembly[] assemblies) where BaseType : ApiEntity
{
IEnumerable<Type> 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);
}
}
}
}