Ef Core花里胡哨系列(5) 动态修改追踪的实体、动态查询
Ef Core花里胡哨系列(5) 动态修改追踪的实体、动态查询
同样还是IModelCacheKeyFactory
,不过这次要采用主动刷新的方式。
实现DbContext
动态实体,根据配置等生成动态类型来当作数据库实体使用,当配置修改时,可以调用DynamicModelCacheKeyFactory.Refresh()
刷新DbContext。
动态构建部分不提供,我们将在其它的地方进行讨论。
public class SampleDbContext(DbContextOptions<SampleDbContext> options)
: DbContext(options)
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// 构建所有的FormType
FormTypeBuilderService.BuildFormTypes();
// 将Type添加到DbContext上下文
foreach (var type in FormTypeBuilderService.Value.GetModelTypes())
{
AddFormEntityType(type);
}
base.OnModelCreating(modelBuilder);
void AddFormEntityType(Type formType)
{
var entityType = modelBuilder.Model.FindEntityType(formType);
if (entityType == null)
{
modelBuilder.Model.AddEntityType(formType);
}
modelBuilder.Entity(formType).HasBaseType((Type)null!);
}
}
}
实现IModelCacheKeyFactory
我这里做了简化处理,直接检测了当前月份的变化,也可以通过实现一个静态变量由外部动态改变。
public class DynamicModelCacheKeyFactory : IModelCacheKeyFactory
{
private static Guid RefreshToken = Guid.NewGuid();
public static Guid Refresh() => Guid.NewGuid();
public object Create(DbContext context, bool designTime)
{
return DateTime.Now.ToString("yyyyMM");
}
}
替换DbContext
中的默认实现
services.AddDbContext<SampleDbContext>(opts =>
{
opts.ReplaceService<IModelCacheKeyFactory, DynamicModelCacheKeyFactory>();
});
派生DbContext
内置方法
实现一个DynamicSet
对标Set<T>
,需要安装System.Linq.Dynamic.Core
和Microsoft.EntityFrameworkCore.DynamicLinq
,即可使用lambda进行拼接查询。
public class SampleDbContext(DbContextOptions<SampleDbContext> options)
: DbContext(options)
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// 构建所有的FormType
FormTypeBuilderService.BuildFormTypes();
// 将Type添加到DbContext上下文
foreach (var type in FormTypeBuilderService.Value.GetModelTypes())
{
AddFormEntityType(type);
}
base.OnModelCreating(modelBuilder);
void AddFormEntityType(Type formType)
{
var entityType = modelBuilder.Model.FindEntityType(formType);
if (entityType == null)
{
modelBuilder.Model.AddEntityType(formType);
}
modelBuilder.Entity(formType).HasBaseType((Type)null!);
}
}
public IQueryable DynamicSet(string tableId)
{
var type = FormTypeBuilderService.GetModelType(tableId);
return (IQueryable)GetType().GetTypeInfo().GetMethod("Set", Type.EmptyTypes)!.MakeGenericMethod(type)
.Invoke(this, null)!;
}
}