Запрос данных в системной версии временной таблицы - PullRequest
4 голосов
/ 27 июня 2019

Мы реализуем решение для запроса временной таблицы любой таблицы.

Как вы знаете, при включении временной таблицы на сервере SQL для любой таблицы SQL автоматически добавит вторую таблицу с дополнительной «_History» в конце таблицы для отслеживания истории. Например, если у нас есть таблица «student», сервер SQL добавит таблицу «student_History».

Чтобы запросить историю учащегося, все, что нам нужно, это запросить таблицу ученика и добавить «FOR SYSTEM_TIME AS OF '2015-09-01 T10: 00: 00.7230011';» в конце утверждения. Поэтому вместо того, чтобы писать:

Выберите * у ученика

Мы напишем: Выберите * у студента ДЛЯ SYSTEM_TIME AS '2015-09-01 T10: 00: 00.7230011'

Есть ли способ автоматически добавить этот оператор в конце запроса?

Это все равно, что перехватывать запрос и применять фильтр запросов, как мягкую таблицу, но теперь он не фильтруется, это просто оператор в конце оператора.

1 Ответ

1 голос
/ 27 июня 2019

это может быть сделано методом расширения, я нашел фрагмент кода, который может помочь вам:

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 , вы можете найти полную статью здесь .

...