在Entity Framework Core中查询系统版本的时态表中的数据。

问题描述 投票:5回答:1

我们正在实现一个查询时态表的解决方案。

当在SQL服务器上为任意表启用时态表时,SQL会自动在表的末尾增加第二张表,并在表的末尾增加额外的"_History "来跟踪历史。例如,如果我们有一个 "学生 "表,SQL服务器将添加 "学生_历史 "表。

如果要查询学生的历史记录,我们只需要查询学生表,并在表中添加 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'

有没有办法在查询的最后自动追加这条语句?

这就好比截取查询,然后像软表一样进行查询过滤,但是现在没有过滤,只是在语句末尾加上了语句。

c# asp.net entity-framework .net-core aspnetboilerplate
1个回答
4
投票

它可以通过一个扩展方法来完成,我发现了一段代码,可能会帮助你。

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 您可以找到完整的文章 此处.

© www.soinside.com 2019 - 2024. All rights reserved.