Use IEntityTypeConfiguration with a base entity

后端 未结 4 992
醉梦人生
醉梦人生 2021-02-05 14:40

In EF Core 2.0, we have the ability to derive from IEntityTypeConfiguration for cleaner Fluent API mappings (source).

How can I extend this pattern to utili

4条回答
  •  时光说笑
    2021-02-05 15:03

    Another approach if you dont want to repeat the column Definitions for all of your Models that inherit from the same base Entity like this:

    protected override void OnModelCreating(ModelBuilder modelBuilder){
            modelBuilder.Entity()
                .Property(b => b.CreatedDateTime)
                .HasDefaultValueSql("CURRENT_TIMESTAMP ");
    
            modelBuilder.Entity()
                .Property(b => b.CreatedDateTime)
                .HasDefaultValueSql("CURRENT_TIMESTAMP ");
            // …
    
    }
    

    is to find all the Entites that inhert from the base Entity, loop over them and call the generic Method as shown below, in which the redundant Logic is placed:

    protected override void OnModelCreating(ModelBuilder modelBuilder){
        foreach (Type type in GetEntityTypes(typeof(BaseEntity))){
            var method = SetGlobalQueryMethod.MakeGenericMethod(type);
            method.Invoke(this, new object[] { modelBuilder });
        }
    }
    
    static readonly MethodInfo SetGlobalQueryMethod = typeof(/*your*/Context)
        .GetMethods(BindingFlags.Public | BindingFlags.Instance)
        .Single(t => t.IsGenericMethod && t.Name == "SetGlobalQuery");
    
    public void SetGlobalQuery(ModelBuilder builder) where T : BaseEntity{
        builder.Entity().Property(o => o.CreatedDateTime).HasDefaultValueSql("CURRENT_TIMESTAMP");
        // Additional Statements
    }
    

    For the "GetEntityTypes" Method you need the Nuget Package „Microsoft.Extensions.DependencyModel“

    private static IList _entityTypeCache;
    private static IList GetEntityTypes(Type type)
    {
        if (_entityTypeCache != null && _entityTypeCache.First().BaseType == type)
        {
            return _entityTypeCache.ToList();
        }
    
        _entityTypeCache = (from a in GetReferencingAssemblies()
                            from t in a.DefinedTypes
                            where t.BaseType == type
                            select t.AsType()).ToList();
    
        return _entityTypeCache;
    }
    
    private static IEnumerable GetReferencingAssemblies()
    {
        var assemblies = new List();
        var dependencies = DependencyContext.Default.RuntimeLibraries;
    
        foreach (var library in dependencies)
        {
            try
            {
                var assembly = Assembly.Load(new AssemblyName(library.Name));
                assemblies.Add(assembly);
            }
            catch (FileNotFoundException)
            { }
        }
        return assemblies;
    }
    

    Its a bit hacky in my opinion, but works fine for me!

    The source with more details:

    https://www.codingame.com/playgrounds/5514/multi-tenant-asp-net-core-4---applying-tenant-rules-to-all-enitites

提交回复
热议问题