在 Entity Framework 核心中的系统版本时间 Table 中查询数据

Querying Data in a System-Versioned Temporal Table in Entity Framework Core

我们正在实施查询时间 table.

的解决方案

当在 SQL 服务器上为任何 table 启用临时 table 时,SQL 将自动添加第二个 table 和额外的“_History” table 结束跟踪历史。例如,如果我们有一个“学生”table,SQL服务器将添加“student_History”table.

要查询学生历史,我们只需要查询学生table并在语句末尾添加FOR SYSTEM_TIME AS OF '2015-09-01 T10:00:00.7230011';。 所以不要写:

Select * from student

我们会写:

Select * from student FOR SYSTEM_TIME AS OF '2015-09-01 T10:00:00.7230011'

有什么方法可以在查询末尾自动追加这条语句吗?

就像拦截查询并应用查询过滤器一样软table,但现在没有过滤,它只是语句末尾的语句。

可以通过扩展方法来完成,我找到了一段可能对您有帮助的代码:

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Migrations;
using System;
using System.Linq;

namespace core
{
    public static class Extensions
    {
        public static void AddTemporalTableSupport(this MigrationBuilder builder, string tableName, string historyTableSchema)
        {
            builder.Sql($@"ALTER TABLE {tableName} ADD 
                            SysStartTime datetime2(0) GENERATED ALWAYS AS ROW START HIDDEN NOT NULL,
                            SysEndTime datetime2(0) GENERATED ALWAYS AS ROW END HIDDEN NOT NULL,
                            PERIOD FOR SYSTEM_TIME (SysStartTime, SysEndTime);");
            builder.Sql($@"ALTER TABLE {tableName} SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = {historyTableSchema}.{tableName} ));");
        }

        public static DbContext GetDbContext<T>(this DbSet<T> dbSet) where T : class
        {
            var infrastructure = dbSet as IInfrastructure<IServiceProvider>;
            return (infrastructure.Instance.GetService(typeof(ICurrentDbContext)) as ICurrentDbContext).Context;
        }

        public static string GetTableName<T>(this DbSet<T> dbSet) where T : class
        {
            var entityType = dbSet.GetDbContext().Model.GetEntityTypes().FirstOrDefault(t => t.ClrType == typeof(T)) 
                ?? throw new ApplicationException($"Entity type {typeof(T).Name} not found in current database context!");
            var tableNameAnnotation = entityType.GetAnnotation("Relational:TableName");
            return tableNameAnnotation.Value.ToString();
        }

        public static IQueryable<T> ForSysTime<T>(this DbSet<T> dbSet, DateTime time) where T : class
        {
            return dbSet.FromSql($"SELECT * FROM dbo.[{dbSet.GetTableName()}] FOR SYSTEM_TIME AS OF {{0}}", time.ToUniversalTime());
        }


    }
}

用法

var date = DateTime.Parse("2018-08-28 16:30:00");
var students = ctx.student.ForSysTime(date);

此扩展方法由Mirek , you can find the complete article here编写。

你可以试试这个 nuget 包 https://www.nuget.org/packages/EntityFrameworkCore.SqlServer.TemporalTable/

支持:

  • 从 Linq 创建时间查询
  • 临时迁移 table。(使用添加迁移、脚本迁移)

最新版本Entity Framework Core (6) 支持临时表。

如此处Microsoft devBlogs所述,EF Core 6.0 支持:

  • 使用 EF Core 迁移创建临时表
  • 再次使用迁移将现有表转换为临时表
  • 正在恢复过去某个时间点的数据
  • 查询历史数据

查询历史数据可以看到here