DataAccessHelper
基于EFCore支持水平分表的工具类
Install / Use
/learn @YinRunhao/DataAccessHelperREADME
DataAccessHelper
一个基于EFCore的工具类,对EFCore中的context操作做了进一步的封装,且支持一个实体类映射多个数据表。
使用方法
如Demo中的例子所示,示例程序中一个Post实体类对应有多个Post数据表,多个数据表按年月存放不同的数据。数据表的命名规则为PostyyyyMM(如Post201910)。
1.新建数据表命名规则提供类,实现ITableMappable接口
// 数据表命名规则提供类,用于根据不同的条件映射不同的数据表
public class PostMapper : ITableMappable
{
// 根据条件返回对应的数据表名
public string GetMappingTableName(Type modelType, object condition)
{
string ret = "";
if (condition is DateTime date)
{
if (modelType == typeof(Post))
{
// Format like Post201906
ret = $"Post{date.ToString("yyyyMM")}";
}
}
return ret;
}
}
2.你的DbContext类需要改动一些代码
请将你代码中的派生自DbContext类改为派生自ExtendDbContext,ExtendDbContext几乎不会改变任何DbContext的行为。
- 将你代码中的派生自DbContext类改为派生自ExtendDbContext
- 实现基类的构造方法,但可以什么都不干
- 把重写OnConfiguring的代码移到Configuring方法中进行重写
- 把重写OnModelCreating的代码移到ModelCreating方法中进行重写
// step1:派生自ExtendDbContext
public partial class BloggingContext : ExtendDbContext
{
public virtual DbSet<Blog> Blog { get; set; }
public virtual DbSet<Post> Post { get; set; }
// step2:实现基类的构造方法,但可以什么都不干
public BloggingContext()
{
}
// step2:实现基类的构造方法,但可以什么都不干
public BloggingContext(ICollection<TableMappingRule> rules):base(rules)
{
}
private static string ConnectString
{
get; set;
}
public static void SetConnectString(string conStr)
{
ConnectString = conStr;
}
// step3:把重写OnConfiguring的代码移到Configuring方法中进行重写
protected override void Configuring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlite(ConnectString)
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
}
}
// step4:把重写OnModelCreating的代码移到ModelCreating方法中进行重写
protected override void ModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>(entity =>
{
entity.HasKey(e => e.BlogId);
entity.ToTable("Blog");
entity.Property(e => e.BlogId).ValueGeneratedNever();
entity.Property(e => e.Url).HasColumnType("VARCHAR (1024)");
});
modelBuilder.Entity<Post>(entity =>
{
entity.HasKey(e => e.PostId);
entity.ToTable("Post");
entity.Property(e => e.PostId).ValueGeneratedNever();
entity.Property(e => e.Content).HasColumnType("VARCHAR (1024)");
entity.Property(e => e.PostDate)
.IsRequired()
.HasColumnType("DATETIME");
entity.Property(e => e.Title).HasColumnType("VARCHAR (512)");
entity.HasOne(e => e.Blog)
.WithMany(b => b.Posts)
.HasForeignKey(e => e.BlogId);
});
}
}
3.正式使用
// 使用示例
static void TestChangeTable(DataAccessor dal, ITableMappable mapper)
{
// 数据表映射条件
DateTime sept = DateTime.Parse("2019-09-05");
DateTime oct = DateTime.Parse("2019-10-05");
// 切换Post实体类的映射的数据表,切换条件为2019年10月,理论上应该切换为数据表 "Post201910"
dal.ChangeMappingTable(typeof(Post), mapper, oct);
// 查询该表下的所有数据
List<Post> octData = dal.GetAll<Post>().ToList();
Console.WriteLine("Oct. data");
foreach (Post item in octData)
{
Console.WriteLine(item);
}
// 切换Post实体类的映射的数据表,切换条件为2019年9月,理论上应该切换为数据表 "Post201909"
dal.ChangeMappingTable(typeof(Post), mapper, sept);
// 查询该表下的所有数据
List<Post> septData = dal.GetAll<Post>().ToList();
Console.WriteLine("Sept. data");
foreach (Post item in septData)
{
Console.WriteLine(item);
}
}
Related Skills
node-connect
338.0kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
83.4kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
338.0kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
83.4kCommit, push, and open a PR
