diff --git a/Examples/efcore_to_freesql/DBContexts/BaseDBContext.cs b/Examples/efcore_to_freesql/DBContexts/BaseDBContext.cs index 69c4326d..86b9529c 100644 --- a/Examples/efcore_to_freesql/DBContexts/BaseDBContext.cs +++ b/Examples/efcore_to_freesql/DBContexts/BaseDBContext.cs @@ -1,3 +1,4 @@ +using efcore_to_freesql.Entitys; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using System; @@ -14,6 +15,15 @@ namespace efcore_to_freesql.DBContexts { base.OnModelCreating(modelBuilder); Fsql.CodeFirst.ConfigEntity(modelBuilder.Model); //同步配置 + + //配置单个 + Fsql.CodeFirst.ApplyConfiguration(new SongConfiguration()); + + //批量量配置 + //Fsql.CodeFirst.ApplyConfigurationsFromAssembly(typeof(SongConfiguration).Assembly); + + Fsql.CodeFirst.SyncStructure(); + } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { diff --git a/Examples/efcore_to_freesql/FreeSqlExtensions/CodeFirstExtensions.cs b/Examples/efcore_to_freesql/FreeSqlExtensions/CodeFirstExtensions.cs index 9dcf1145..16c870ef 100644 --- a/Examples/efcore_to_freesql/FreeSqlExtensions/CodeFirstExtensions.cs +++ b/Examples/efcore_to_freesql/FreeSqlExtensions/CodeFirstExtensions.cs @@ -1,5 +1,6 @@ 锘縰sing efcore_to_freesql.Entitys; using FreeSql; +using FreeSql.Extensions.EfCoreFluentApi; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata; using System; @@ -178,4 +179,27 @@ public static class CodeFirstExtensions cf.SyncStructure(); cf.SyncStructure(); } -} \ No newline at end of file +} + +public class SongConfiguration : FreeSql.Extensions.EfCoreFluentApi.IEntityTypeConfiguration +{ + public void Configure(EfCoreTableFluent eb) + { + eb.ToTable("tb_song_config"); + eb.Ignore(a => a.Field1); + eb.Property(a => a.Title).HasColumnType("varchar(50)").IsRequired(); + eb.Property(a => a.Url).HasMaxLength(100); + + eb.Property(a => a.RowVersion).IsRowVersion(); + eb.Property(a => a.CreateTime).HasDefaultValueSql("current_timestamp"); + + eb.HasKey(a => a.Id); + eb.HasIndex(a => a.Title).IsUnique().HasName("idx_tb_song1111"); + + //涓瀵瑰銆佸瀵逛竴 + eb.HasOne(a => a.Type).HasForeignKey(a => a.TypeId).WithMany(a => a.Songs); + + //澶氬澶 + eb.HasMany(a => a.Tags).WithMany(a => a.Songs, typeof(Song_tag)); + } +} diff --git a/Examples/efcore_to_freesql/Startup.cs b/Examples/efcore_to_freesql/Startup.cs index 3debf0b1..0a89b54c 100644 --- a/Examples/efcore_to_freesql/Startup.cs +++ b/Examples/efcore_to_freesql/Startup.cs @@ -28,7 +28,7 @@ namespace efcore_to_freesql .Build(); //Fsql.CodeFirst.EfCoreFluentApiTestGeneric(); - Fsql.CodeFirst.EfCoreFluentApiTestDynamic(); + //Fsql.CodeFirst.EfCoreFluentApiTestDynamic(); BaseDBContext.Fsql = Fsql; diff --git a/FreeSql.DbContext/EfCoreFluentApi/EfCoreFluentApiExtensions.cs b/FreeSql.DbContext/EfCoreFluentApi/EfCoreFluentApiExtensions.cs index f6974811..f09367a4 100644 --- a/FreeSql.DbContext/EfCoreFluentApi/EfCoreFluentApiExtensions.cs +++ b/FreeSql.DbContext/EfCoreFluentApi/EfCoreFluentApiExtensions.cs @@ -1,6 +1,8 @@ 锘縰sing System; using System.Collections.Generic; +using System.Linq; using System.Linq.Expressions; +using System.Reflection; using FreeSql; using FreeSql.DataAnnotations; using FreeSql.Extensions.EfCoreFluentApi; @@ -34,4 +36,103 @@ partial class FreeSqlDbContextExtensions codeFirst.ConfigEntity(entityType, tf => modelBuilder(new EfCoreTableFluent(cf._orm, tf, entityType))); return codeFirst; } + + public static ICodeFirst ApplyConfiguration(this ICodeFirst codeFirst, IEntityTypeConfiguration configuration) where TEntity : class + { + return codeFirst.Entity(eb => + { + configuration.Configure(eb); + }); + } +#if net40 +#else + static IEnumerable GetExtensionMethods(this Assembly assembly, Type extendedType) + { + var query = from type in assembly.GetTypes() + where !type.IsGenericType && !type.IsNested + from method in type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) + where method.IsDefined(typeof(System.Runtime.CompilerServices.ExtensionAttribute), false) + where method.GetParameters()[0].ParameterType == extendedType + select method; + return query; + } + + /// + /// 鏍规嵁Assembly鎵弿鎵鏈夌户鎵縄EntityTypeConfiguration<T>鐨勯厤缃被 + /// + /// + /// + /// + /// + public static ICodeFirst ApplyConfigurationsFromAssembly(this ICodeFirst codeFirst, Assembly assembly, Func predicate = null) + { + IEnumerable typeInfos = assembly.DefinedTypes.Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition); + + MethodInfo methodInfo = typeof(FreeSqlDbContextExtensions).Assembly.GetExtensionMethods(typeof(ICodeFirst)) + .Single((e) => e.Name == "Entity" && e.ContainsGenericParameters); + + if (methodInfo == null) return codeFirst; + + foreach (TypeInfo constructibleType in typeInfos) + { + if (constructibleType.GetConstructor(Type.EmptyTypes) == null || predicate != null && !predicate(constructibleType)) + { + continue; + } + + foreach (var @interface in constructibleType.GetInterfaces()) + { + if (@interface.IsGenericType && @interface.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>)) + { + var type = @interface.GetGenericArguments().First(); + var efFluentType = typeof(EfCoreTableFluent<>).MakeGenericType(type); + var actionType = typeof(Action<>).MakeGenericType(efFluentType); + + //1.闇瑕佸疄浣撳拰Configuration閰嶇疆 + //codeFirst.Entity(eb => + //{ + // new ToDoItemConfiguration().Configure(eb); + //}); + + //2.闇瑕佸疄浣 + //Action> x = new Action>(e => + //{ + // object o = Activator.CreateInstance(constructibleType); + // constructibleType.GetMethod("ApplyConfiguration")?.Invoke(o, new object[1] { e }); + //}); + //codeFirst.Entity(x); + + //3.瀹炵幇鍔ㄦ佽皟鐢ㄦ硾鍨嬪鎵 + DelegateBuilder delegateBuilder = new DelegateBuilder(constructibleType); + MethodInfo applyconfigureMethod = delegateBuilder.GetType().GetMethod("ApplyConfiguration")?.MakeGenericMethod(type); + if (applyconfigureMethod == null) continue; + Delegate @delegate = Delegate.CreateDelegate(actionType, delegateBuilder, applyconfigureMethod); + + methodInfo.MakeGenericMethod(type).Invoke(null, new object[2] + { + codeFirst, + @delegate + }); + + } + } + } + + return codeFirst; + } + class DelegateBuilder + { + private readonly Type type; + + public DelegateBuilder(Type type) + { + this.type = type; + } + public void ApplyConfiguration(EfCoreTableFluent ex) + { + object o = Activator.CreateInstance(type); + type.GetMethod("Configure")?.Invoke(o, new object[1] { ex }); + } + } +#endif } diff --git a/FreeSql.DbContext/EfCoreFluentApi/IEntityTypeConfiguration.cs b/FreeSql.DbContext/EfCoreFluentApi/IEntityTypeConfiguration.cs new file mode 100644 index 00000000..ead5574f --- /dev/null +++ b/FreeSql.DbContext/EfCoreFluentApi/IEntityTypeConfiguration.cs @@ -0,0 +1,7 @@ +锘縩amespace FreeSql.Extensions.EfCoreFluentApi +{ + public interface IEntityTypeConfiguration where TEntity : class + { + void Configure(EfCoreTableFluent model); + } +} \ No newline at end of file