EFCore 分表

Program

internal class Program
{
    static async Task Main(string[] args)
    {
        DbContextOptionsBuilder<BloggingContext> optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
        optionsBuilder.UseSqlServer("Data Source=localhost;Initial Catalog=DemoA;Integrated Security=True;Encrypt=True;TrustServerCertificate=True;");
        var options = optionsBuilder.Options;

        using (var dbContext1 = new BloggingContext("202209", options))
        {
            var blog = dbContext1.Blogs.FirstOrDefault();
            Console.WriteLine("查询成功: dbContext1");
        }

        using (var dbContext2 = new BloggingContext("202210", options))
        {
            var blog = dbContext2.Blogs.FirstOrDefault();
            Console.WriteLine("查询成功: dbContext2");
        }

        Console.ReadKey();
    }
}

BloggingContext

public class BloggingContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    public string ShardingRule { get; }

    public BloggingContext(string shardingRule, DbContextOptions options) : base(options)
    {
        this.ShardingRule = shardingRule;
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        base.OnConfiguring(optionsBuilder);

        if (!string.IsNullOrWhiteSpace(this.ShardingRule))
        {
            optionsBuilder.ReplaceService<IModelCacheKeyFactory, DynamicModelCacheKeyFactoryDesignTimeSupport>()
                          .ReplaceService<IModelCustomizer, ShardingModelCustomizer>();
        }
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
    }
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

DynamicModelCacheKeyFactoryDesignTimeSupport

/// <summary>
/// 同一DBContext仅能执行OnModelCreating一次,自定义 IModelCacheKeyFactory,实现多次触发
/// </summary>
public class DynamicModelCacheKeyFactoryDesignTimeSupport : IModelCacheKeyFactory
{
    public object Create(DbContext context, bool designTime)
    {
        return context is BloggingContext bloggingContext 
            ? (context.GetType(), bloggingContext.ShardingRule, designTime)
            : context.GetType();
    }

    public object Create(DbContext context)
       => Create(context, false);
}

ShardingModelCustomizer

/// <summary>
/// 修改模型定义
/// </summary>
public class ShardingModelCustomizer : ModelCustomizer
{
    public ShardingModelCustomizer(ModelCustomizerDependencies dependencies) : base(dependencies)
    {
    }

    public override void Customize(ModelBuilder modelBuilder, DbContext context)
    {
        base.Customize(modelBuilder, context);

        var bloggingContext = context as BloggingContext;
        if (bloggingContext == null) return;

        // 这里为了演示,仅以Blog实体做演示。
        var type = typeof(Blog);

        // 映射到自定表
        modelBuilder.Entity(type).ToTable($"{type.Name}_{bloggingContext.ShardingRule}");
    }
}
posted @ 2024-10-07 16:30  pojianbing  阅读(6)  评论(0编辑  收藏  举报