如何通过EF Core将历史快照导入指定有效日期的Temporal Table?
不用改SQL Server系统时间,这样用EF Core导入历史数据到时态表
核心思路:临时关闭系统版本控制,手动指定有效时间
SQL Server时态表默认自动管理SysStartTime和SysEndTime,但导入历史数据时,我们可以临时关掉自动版本控制,手动给这两个字段赋值,之后再恢复自动控制,完全不用碰系统时间。
具体操作步骤
- 第一步:先关掉目标时态表的系统版本控制
ALTER TABLE [你的表名] SET (SYSTEM_VERSIONING = OFF);
- 第二步:用EF Core或者直接SQL插入历史数据,手动指定生效和失效时间
比如导入昨日的快照,就把SysStartTime设为昨日0点,SysEndTime设为今日0点;如果是当前仍有效的数据,SysEndTime设为9999-12-31 23:59:59.9999999(SQL Server时态表的默认最大值)。
EF Core里要先把这两个字段配置成允许手动赋值:
protected override void OnModelCreating(ModelBuilder modelBuilder) { var entity = modelBuilder.Entity<你的实体类>(); // 取消自动生成,允许手动设置时间 entity.Property(e => e.SysStartTime) .HasColumnName("SysStartTime") .ValueGeneratedNever(); entity.Property(e => e.SysEndTime) .HasColumnName("SysEndTime") .ValueGeneratedNever(); // 配置时态表(如果之前没配置的话) entity.ToTable(tb => tb.IsTemporal(tt => { tt.UseHistoryTable("对应的历史表名"); tt.HasPeriodStart("SysStartTime"); tt.HasPeriodEnd("SysEndTime"); })); }
然后直接给实体赋值插入就行:
var historicalData = new 你的实体类 { Id = 1, 其他字段 = "对应值", SysStartTime = new DateTime(2024, 5, 20, 0, 0, 0, DateTimeKind.Utc), SysEndTime = new DateTime(2024, 5, 21, 0, 0, 0, DateTimeKind.Utc) }; dbContext.你的实体集合.Add(historicalData); await dbContext.SaveChangesAsync();
- 第三步:重新开启系统版本控制
ALTER TABLE [你的表名] SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [对应的历史表名]));
补充方案:直接写历史表(补旧历史版本)
如果主表已经有当前有效数据,只是要补之前的历史快照,不用动主表,直接往历史表里插数据就行,历史表结构和主表完全一致,同样指定SysStartTime和SysEndTime。
适配你的Docker架构的建议
- 导入服务单独执行上述操作就行,执行期间暂时别让ASP.NET Core应用写这个表,避免冲突,完全不影响正常查询。
- 以后每日更新数据不用特殊处理:正常修改数据,SQL Server会自动把旧版本写到历史表,时态表的机制会正常工作。
- 新增数据集时,重复上面的步骤就行,全程不用碰SQL Server容器的系统时间,彻底避免系统时间错误导致的查询问题。
内容的提问来源于stack exchange,提问作者Marius Steinbach
相关产品推荐
相关产品推荐

