在 ASP.Net Core 中使用 History 表存储历史数据

Posted

技术标签:

【中文标题】在 ASP.Net Core 中使用 History 表存储历史数据【英文标题】:Storing Historical Data using History table in ASP.Net Core 【发布时间】:2021-03-17 18:31:38 【问题描述】:

我的数据库中有一个实体与多个实体相关联,我需要为基础实体和子实体中的更改(插入、更新和删除)存储历史数据。

现在我们正在考虑采用的方法是将每个数据保留在相应的历史实体中。基表如下所示:

public partial class Con 

    public Guid Id  get; set; 
    public string Note  get; set; 
    ...
    public virtual ICollection<Document> Document  get; set; 
    public virtual ICollection<ConLine> ConLine  get; set; 
    public virtual ICollection<Leg> Leg  get; set; 

而历史表是这样的,我不知道如何设计历史表来保存链接表数据

public partial class ConHistory 

    public Guid Id  get; set; 
    public Guid ConId  get; set; 
    public int TransactionId  get; set; 
    ...
    public virtual ICollection<Document> Document  get; set; 
    public virtual ICollection<ConLine> ConLine  get; set; 
    public virtual ICollection<Leg> Leg  get; set; 

我该如何解决这个问题?最好的行业做法是什么?我主要关心的是当孩子的数据被更改时,我如何登录到父历史表和相应的子历史表。

【问题讨论】:

【参考方案1】:

对于简单的时间序列数据,保留一个包含可修改字段副本的单独表格是一种非常有效的方法。不幸的是,在您的情况下,您还需要制作每个链接表的副本,以便您可以保持一致的外键 - 例如DocumentHistoryConLineHistoryLegHistory。这是很多重复的代码。然后您必须考虑,架构更改时所有历史记录会发生什么变化?

就我个人而言,我会将这些信息以 json 格式存储在文本列中。您搜索的所有字段都应该在sql中,以便您可以对其进行索引,但其余的可以序列化为json字符串:

public partial class ConHistory 

    public Guid Id  get; set; 
    public Guid ConId  get; set; 
    public int TransactionId  get; set; 
    public Guid ModifiedByUser  get; set; 
    public DateTime Date  get; set; 

    // Serialize the rest of the `ConHistory` fields to a json object, and store them here
    public string Json  get; set; 

Sql 也有JSON_VALUE 函数,如果您确实需要从 json 字符串中获取值进行查询,有一些在 Entity Framework 中使用它的示例。

【讨论】:

感谢您的洞察力。我需要查询历史数据进行审计。每次运行查询时,我都必须将 json 数据转换为实际对象吗?还是有其他方法可用? 所有这些数据的另一件事:con、conline、document、leg 将在同一个事务中发布。如果我们保留单独的历史记录表,您将如何处理这种情况? 您可以创建一个自定义ValueConverter 来处理从 json 到强类型对象的转换。根据您的第二条评论,我不确定我是否理解问题所在,但我会尽力解决。 如果您决定将它们全部保存在单独的历史表中,您可以:只需插入父对象,EF 将遍历导航属性并将子对象也添加到相应的表中。或者:您可以将逻辑保存在数据库中,在 SQL 插入触发器中。我不确定你在说什么卷,但是 EntityFramework 在插入复杂的层次结构时有点慢。它一个一个地插入各个实体,并等待 id 回来。对于小吞吐量,这很好,对于大吞吐量,它不是。

以上是关于在 ASP.Net Core 中使用 History 表存储历史数据的主要内容,如果未能解决你的问题,请参考以下文章

在 ASP.NET Core 6.0 中使用 Serilog

如何在 ASP.Net Core 中使用 IHostedService

ASP.NET Core Web 应用程序系列- 在ASP.NET Core中使用Autofac替换自带DI进行批量依赖注入(MVC当中应用)

asp.net core中托管SPA应用

如何使用 EF Core 在 ASP.NET Core 中取消应用迁移

ASP.NET Core中使用Swagger