- A+
所属分类:.NET技术
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)!; } }