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}");
}
}