簡體   English   中英

在 Entity Framework Core 中的系統版本化臨時表中查詢數據

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

我們正在實施一個查詢臨時表的解決方案。

在 SQL Server 上為任何表啟用臨時表時,SQL 將自動在表末尾添加帶有額外“_History”的第二個表以跟蹤歷史記錄。 例如,如果我們有一個“student”表,SQL Server 會添加“student_History”表。

要查詢學生歷史,我們只需要查詢學生表並添加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'

有沒有辦法在查詢的末尾自動附加這個語句?

就像一個軟表一樣攔截查詢並應用查詢過濾器,但現在它沒有過濾,它只是語句末尾的語句。

它可以通過擴展方法來完成,我找到了一段可以幫助你的代碼:

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編寫,您可以在此處找到完整的文章。

你可以試試這個 nuget pacakge https://www.nuget.org/packages/EntityFrameworkCore.SqlServer.TemporalTable/

IT支持:

  • 從 Linq 創建時間查詢
  • 時態表的遷移。(使用 Add-Migration、Script-Migration)

最新版本的 Entity Framework Core (6) 支持時態表。

正如此處提到的Microsoft devBlogs EF Core 6.0 支持:

  • 使用 EF Core 遷移創建時態表
  • 再次使用遷移將現有表轉換為臨時表
  • 從過去的某個時間點恢復數據
  • 查詢歷史數據

查詢歷史數據可以看這里

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM