Ef Core花里胡哨系列(3) 动态修改实体对应的表(分表)、多租户

发布时间 2024-01-02 12:14:15作者: 胖纸不争

Ef Core花里胡哨系列(3) 动态修改实体对应的表(分表)、多租户

Ef Core在加载的时候,会执行一次OnModelCreating用来加载所用到的实体。我们要做的就是刷新Ef Core上下文中之前缓存的内容。

分表

我们假如有一个程序,会每个月创建一个Table年月的表,我们要做的是每个月只查询当前月的表,更复杂的逻辑我们以后再来讨论,先了解基本的原理。

如何刷新DbContext?

Ef Core通过IModelCacheKeyFactory来检查当前DbContext是否发生了变化。如果发生了变化,将会重新执行一次OnModelCreating

那么事情就很简单了,我们需要自动或者手动让IModelCacheKeyFactory产生的Key发生变化,OnModelCreating中做好对应的处理就可以了。

实现DbContext

User实体映射到User年月的表上。

如果报错没有ToTable方法,添加Microsoft.EntityFrameworkCore.Relational的引用即可。

public class SampleDbContext(DbContextOptions<SampleDbContext> options)
    : DbContext(options)
{
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>().ToTable($"User{DateTime.Now.ToString("yyyyMM")}");

        base.OnModelCreating(modelBuilder);
    }
}

实现IModelCacheKeyFactory

我这里做了简化处理,直接检测了当前月份的变化,也可以通过实现一个静态变量由外部动态改变。

public class MyModelCacheKeyFactory : IModelCacheKeyFactory
{
    public object Create(DbContext context, bool designTime)
    {
        return DateTime.Now.ToString("yyyyMM");
    }
}

替换DbContext中的默认实现

services.AddDbContext<SampleDbContext>(opts =>
{
    opts.ReplaceService<IModelCacheKeyFactory, MyModelCacheKeyFactory>();
});

多租户

利用这些类似的实现,我们可以实现基于分表的多租户,只需要将实体和租户标识映射到不同的表即可。

后面我会说明如何基于多库、Schema进行多租户管理。