mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-04-22 10:42:52 +08:00
Merge pull request #937 from luoyunchong/dev
支持Fluent API .以继承接口的形式配置实体的。
This commit is contained in:
commit
a1f029a086
@ -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<Song>();
|
||||
|
||||
}
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
|
@ -1,5 +1,6 @@
|
||||
using 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<SongType>();
|
||||
cf.SyncStructure<Song>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SongConfiguration : FreeSql.Extensions.EfCoreFluentApi.IEntityTypeConfiguration<Song>
|
||||
{
|
||||
public void Configure(EfCoreTableFluent<Song> 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));
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ namespace efcore_to_freesql
|
||||
.Build();
|
||||
|
||||
//Fsql.CodeFirst.EfCoreFluentApiTestGeneric();
|
||||
Fsql.CodeFirst.EfCoreFluentApiTestDynamic();
|
||||
//Fsql.CodeFirst.EfCoreFluentApiTestDynamic();
|
||||
|
||||
BaseDBContext.Fsql = Fsql;
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
using 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<TEntity>(this ICodeFirst codeFirst, IEntityTypeConfiguration<TEntity> configuration) where TEntity : class
|
||||
{
|
||||
return codeFirst.Entity<TEntity>(eb =>
|
||||
{
|
||||
configuration.Configure(eb);
|
||||
});
|
||||
}
|
||||
#if net40
|
||||
#else
|
||||
static IEnumerable<MethodInfo> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据Assembly扫描所有继承IEntityTypeConfiguration<T>的配置类
|
||||
/// </summary>
|
||||
/// <param name="codeFirst"></param>
|
||||
/// <param name="assembly"></param>
|
||||
/// <param name="predicate"></param>
|
||||
/// <returns></returns>
|
||||
public static ICodeFirst ApplyConfigurationsFromAssembly(this ICodeFirst codeFirst, Assembly assembly, Func<Type, bool> predicate = null)
|
||||
{
|
||||
IEnumerable<TypeInfo> 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<ToDoItem>(eb =>
|
||||
//{
|
||||
// new ToDoItemConfiguration().Configure(eb);
|
||||
//});
|
||||
|
||||
//2.需要实体
|
||||
//Action<EfCoreTableFluent<ToDoItem>> x = new Action<EfCoreTableFluent<ToDoItem>>(e =>
|
||||
//{
|
||||
// object o = Activator.CreateInstance(constructibleType);
|
||||
// constructibleType.GetMethod("ApplyConfiguration")?.Invoke(o, new object[1] { e });
|
||||
//});
|
||||
//codeFirst.Entity<ToDoItem>(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<T>(EfCoreTableFluent<T> ex)
|
||||
{
|
||||
object o = Activator.CreateInstance(type);
|
||||
type.GetMethod("Configure")?.Invoke(o, new object[1] { ex });
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -0,0 +1,7 @@
|
||||
namespace FreeSql.Extensions.EfCoreFluentApi
|
||||
{
|
||||
public interface IEntityTypeConfiguration<TEntity> where TEntity : class
|
||||
{
|
||||
void Configure(EfCoreTableFluent<TEntity> model);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user