EF Core之自动历史记录

2023-05-16

EF Core之自动历史记录

有的场景下需要记录特定表的增删改操作,以便追溯。传统的做法是在增删改的方法里同步做记录,很繁琐。在这里我们可以配合EF Core的DBContext做一个全局管控

  • 全局管控自然就要有固定的格式

    • 我们可以建一个空接ITrackable口来标明需要追踪的表:

      public interface ITrackable
      {
      }
      
    • 对于需要追踪的表,实现ITrackable作为标识:

      public class TableNeedTrack : ITrackable
      {
      }
      
    • 为历史记录表提供一个接口:

      public interface IHistory
      {
          /// <summary>
          /// 记录时间
          /// </summary>
          DateTime Hist_Created { get; set; }
          /// <summary>
          /// 记录行为
          /// </summary>
          string Hist_Action { get; set; }
          /// <summary>
          /// 记录对象id
          /// </summary>
          int? Hist_SourceId { get; set; }
      }
      
    • 对于历史记录表,实现IHistory,命名必须严格按照{TableNeedTrack}_Hist的格式,以便全局管控:

      public class TableNeedTrack_Hist : IHistory
      {
          /// <summary>
          /// Id
          /// </summary>
          public int Id { get; set; }
          /// <summary>
          /// 记录时间
          /// </summary>
          [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
          public DateTime Hist_Created { get; set; } = DateTime.Now;
          /// <summary>
          /// 记录行为
          /// </summary>
          public string Hist_Action { get; set; }
          /// <summary>
          /// 记录对象id
          /// </summary>
          public int? Hist_SourceId { get; set; }
      }
      
      • 历史记录有两种方式:1.将所有变化记录在一个Json字符串(判断真正变更的字符比较麻烦也损耗性能,不一定有必要);2.把原对象所有字段复制到历史记录表(本文选用此方法作为说明);
  • 做好以上准备后,就可以到DBContext里做全局管控了:

    //在SaveChanges里管控历史记录,这样就可以做到全自动处理
    public override int SaveChanges(bool acceptAllChangesOnSuccess)
    {
        //获取原始历史记录
        var histEntries = OnBeforeSaving();
        //自动保存
        var result = base.SaveChanges(acceptAllChangesOnSuccess);
        //保存后再添加历史记录:有的信息需要数据库生成,比如id在保存前的话会得到-2147482647
        OnAfterSaving(histEntries);
        return result;
    }
    
    /// <summary>
    /// 保存前的操作:历史记录
    /// </summary>
    /// <returns>历史记录基础数据</returns>
    private List<HistoryEntry> OnBeforeSaving()
    {
        //预先保留需要做历史记录且有更改的Entry
        var histEntries = ChangeTracker.Entries<ITrackable>()
                                       .Where(e => e.State != EntityState.Detached && e.State != EntityState.Unchanged)
                                       .Select(e => new HistoryEntry { EntityEntry = e, State = e.State.ToString() })
                                       .ToList();
        return histEntries;
    }
    
    /// <summary>
    /// 保存后的操作:保存历史记录
    /// </summary>
    /// <param name="entries">历史记录基础数据</param>
    private void OnAfterSaving(List<HistoryEntry> entries)
    {
        if (entries.IsNullOrEmpty())
        {
            //这里很重要,确保只做正确的历史记录,保证历史记录的记录不能进行
            return;
        }
    
        foreach (var entry in entries)
        {
            var entity = (IEntity)entry.EntityEntry.Entity;
    
            Type entityType = entity.GetType();
            //历史记录必须和原对象同命名空间,名字=原对象+"_Hist"的格式
            var histTypeName = $"{entityType.Namespace}.{entityType.Name + "_Hist"}, {entityType.GetTypeInfo().Assembly.FullName}";
            Type histType = Type.GetType(histTypeName, false);
            if (histType != null)
            {
                var histEntity = (IHistory)Activator.CreateInstance(histType);
                if (histEntity != null)
                {
                    var histFields = histType.GetTypeInfo().GetProperties(BindingFlags.Public | BindingFlags.Instance).ToDictionary(k => k.Name);
                    var entityFields = entityType.GetTypeInfo().GetProperties(BindingFlags.Public | BindingFlags.Instance);
                    //这里过滤了Id(主键)
                    foreach (var field in entityFields.Where(af => histFields.ContainsKey(af.Name) && af.Name != "Id").ToList())
                    {
                        //将修改内容赋值给历史记录表同样的字段
                        var value = field.GetValue(entity);
                        histFields[field.Name].SetValue(histEntity, value);
                    }
    
                    histEntity.Hist_SourceId = entity.Id;
                    histEntity.Hist_Action = entry.State;
                    Add(histEntity);
                }
            }
        }
    
        SaveChanges();
    }
    
  • 这样就能够实现自动历史记录了

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

EF Core之自动历史记录 的相关文章

  • Linux遇到Aborted (core dumped)

    1 问题描述 或出现 xff1a 2 关于Core Dump的分析 2 1 什么是Core Dump Core的意思是内存 Dump的意思是扔出来 堆出来 在开发 xff08 或使用 xff09 一个程序时 xff0c 有时程序莫名其妙的d
  • ASP.NET Core 3.0 : 二十四. 配置的Options模式

    上一章讲到了配置的用法及内部处理机制 xff0c 对于配置 xff0c ASP NET Core还提供了一种Options模式 ASP NET Core 系列目录 一 Options的使用 上一章有个配置的绑定的例子 xff0c 可以将配置
  • core dumped 错误

    Aborted xff08 core dumpde xff09 一般是关于内存异常 xff1a 详细解释 gdb使用 1 往受到系统保护的内存地址写数据 有些内存是内核占用的或者是其他程序正在使用 xff0c 为了保证系统正常工作 xff0
  • 记录一次rviz无法启动,报错segmentation fault (core dumped)的解决过程

    起因 好久没有使用ROS相关程序了 xff0c 突然想运行莫程序发现rviz打不开 仔细定位后发现在终端直接输入rviz也无法打开 经过 在网上尝试搜索了好几个小时 xff0c 尝试了以下各种方法 xff0c 更新3D graphics l
  • 记一次 jenkins 构建失败 “Cannot find module ‘core-js/modules/es.promise.finally‘”

    目录 前言排查过程解决方案总结 前言 这是一次前端项目构建失败的惨案 xff0c 项目已经部署很久了 xff0c 一直相安无事 因为开发更新了代码 xff0c 在构建的时候报错 xff1a main js Cannot find modul
  • linux tty core 源码分析__tty_read,__tty_write,__tty_poll,

    转载 xff1a http blog csdn net sirzjp article details 6134489 前面分析了open操作 xff0c 现在分析读操作tty read tty read直接调用线路规程中的读操作从tty g
  • Asp.Net Core中的各种过滤器(授权、资源、操作、结果、异常)

    Asp Net Core中的各种过滤器 授权 资源 操作 结果 异常
  • core dumped ?完了?

    微信公众号 xff1a linux码头 core dumped xff1a 当程序在运行过程中发生异常 xff0c 这时linux系统可以把程序出错的内存 内容存储在一个core文件中 xff0c 又叫核心转存 应用程序在运行过程汇总经常会
  • STM32 usb_core.c分析

    usb core c这个c文件是个庞大的文件 xff0c 主要是定义了usb2 0的标注协议处理函数 下面是这个文件的所有函数 xff1a Function Name Standard GetConfiguration Descriptio
  • Aborted (core dumped)

    在百度谷歌了无数次之后 xff0c 看了许多关于Aborted xff08 core dumped xff09 的解决方法后 xff0c 终于找到一个解决办法 文章来自 http blog 163 com wujiaxing009 64 1
  • Linux下core文件产生的一些注意问题

    前面转载了一篇文章关于core文件的产生和调试使用的设置 xff0c 但在使用有一些需要注意的问题 xff0c 如 在什么情况 才会正确地产生core文件 列出一些常见问题 xff1a 一 xff0c 如何使用core文件 1 使用core
  • 开core信息

    ulimit c unlimited
  • django调试问题django.core.exceptions.ImproperlyConfigured

    django项目调试子应用app时提示缺少配置 1 项目的settings文件里面设置的有子app xff0c 依旧提示下面问题 django core exceptions ImproperlyConfigured Requested s
  • 快速入门ASP.NET Core

    本来这篇只是想简单介绍下ASP NET Core MVC项目的 毕竟要照顾到很多新手朋友 但是转念一想不如来点猛的 考虑到急性子的朋友 让你通过本文的学习就能快速的入门ASP NET Core 既然是快速入门所以过多过深的内容我这里就一笔带
  • 覆盖java文本区域的内容

    我每隔一秒将文本附加到文本区域 我想覆盖或清除旧文本 并且我想每隔一秒写入新数据 如何在java中执行此操作 谢谢罗刹 我猜你说的是 SwingJTextArea 你可以打电话setText 在其上替换文本 JTextArea textAr
  • Nuget ITfoxtec SAML 和 Angular

    我对 nuget 示例中描述的功能和我的案例 特别是 core 和 Angular 中描述的功能有疑问 我有一个带有 angular4 的前端 所有请求都通过那里 我用它重定向到 Idp 表格 他再次打电话给我 将断言传递给我 如何使用 A
  • Java:JVM 可用的内核?

    Java中有这样的方法Runtime getRuntime availableProcessors 其中有以下 Javadoc 返回 Java 虚拟机可用的处理器数量 该值可能会在虚拟机的特定调用期间发生变化 价值实际上如何改变 例如 在什
  • 如何摆脱 Core 中的“let”?

    我有一个在内部循环中频繁调用的函数 它看起来像这样 import qualified Data Vector Storable as SV newtype Timedelta Timedelta Double cklsLogDens SV
  • 扩展 jQuery 核心的用处

    我发现了一种扩展核心 jQuery init 函数的方法 每当您使用 或 jQuery 函数时都会调用该函数 使用普通代理模式不可能做到这一点 但以下代码可以使其工作 var origInit jQuery fn init jQuery f
  • 将整数列表转换为 int 数组[重复]

    这个问题在这里已经有答案了 有没有办法将整数列表转换为整数数组 不是整数 类似于 List 到 int 的东西 无需循环遍历列表并手动将 intger 转换为 int 您可以使用toArray得到一个数组Integers ArrayUtil

随机推荐

  • spring框架的简单配置步骤——小马同学@Tian

    spring框架配置步骤 1 导入jar包 本教程使用spring5 1 5 xff0c 在pom xml中进行导入依赖 Maven方式 xff1a span class token tag span class token tag spa
  • PSReadLine - Powershell 的强化工具

    PSReadLine Powershell 的强化工具 UPDATE 2022 3 4 根据其 Github README 的说明 xff0c If you are using Windows PowerShell on Windows 1
  • 美化 PowerShell

    美化 PowerShell UPDATE 2022 3 4 本文使用的 oh my posh 基于 V2 版本 xff0c 而更新且功能更强大的新版本已经发布 xff0c 如需使用请参考其官方文档 1 准备工作 Step1 下载并安装 Po
  • nltk下载语料库

    1 首先我们使用命令pip list查看是否安装了nltk模块 xff0c 如果没有 xff0c 则执行命令pip3 install nltk进行安装 2 之后 xff0c 我们在Jupyter Notebook中进行语料库的安装 impo
  • Spark scala和java的api使用

    Spark scala和java的api使用 1 利用scala语言开发spark的worcount程序 xff08 本地运行 xff09 package com zy spark import org apache spark rdd R
  • 解决Ubuntu18.04循环登录/卡在开机界面/无法进入图形界面的问题

    原因 xff1a NVIDIA显卡驱动损坏 解决方案 xff1a 重启进入命令行模式卸载原有NVIDIA驱动程序重新安装NVIDIA驱动后重启 xff0c 问题解决 Step1 Ubuntu系统开机进入命令行模式 系统启动后 xff0c 在
  • C++ 遍历注册表项下的所有键和值

    include 34 stdafx h 34 include lt time h gt include lt windows h gt include lt iostream gt include lt stdio h gt include
  • 9月10日美团网2014校招研发笔试哈尔滨站

    1 链表翻转 给出一个链表和一个数k xff0c 比如链表1 2 3 4 5 6 xff0c k 61 2 xff0c 则翻转后2 1 4 3 6 5 xff0c 若k 61 3 翻转后3 2 1 6 5 4 xff0c 若k 61 4 x
  • 2014校园招聘京东软件开发类笔试(完整版)

    时间 xff1a 2013 9 10 2013 10 8 地点 xff1a 四川大学 天津大学 职位 xff1a 软件开发工程师岗 语言 xff1a java 1 A 2 C 3 D 4 B 5 A 二 1 B 三1 D 2 B 3 C 4
  • Win8.1电脑声音可以外放但是插入耳机没有声音

    今天早上正准备学习英语 xff0c 发现耳机插入电脑没有声音 xff0c 于是开始找百度 xff0c 一步一步剥茧抽丝去查找问题来源 问题 xff1a 点击喇叭出现如下图片 xff1a 平常只有右半个图现在却有两个图标了 步骤 xff1a
  • 在线购物系统问题描述&领域词汇表

    在线购物问题描述 v2 0 时间 2017年 4月19日星期三 参与者在线客户能够通过网站完成在线购物 xff0c 顶层用况包括商品信息浏览 购物 咨询 用户注册 xff0c 用户登录 用户反馈 浏览商品用况可以用于客户寻找和浏览想要看的商
  • 在线购物领域类图

  • 在线购物系统用况分析

    一 系统用况图 1 用况图 2 xff08 1 xff09 用况图综述 系统主要是使顾客方便安全地购物 xff0c 已注册顾客可以通过系统查找 浏览 购买商品 xff0c 并且能够进行评价商品 与相应的商家沟通 或者向网站管理人员反馈问题
  • 被做成类似通信图的分析类图

    实验二博客 xff1a http blog csdn net simonruyang article details 70332294 一 注册 1 图形如下 2 文字说明 xff08 1 xff09 类图综述 目的 xff1a 让未注册顾
  • 顺序图实验记录,又懒又差劲,好懒好懒

    实验二博客 xff1a http blog csdn net simonruyang article details 70332294 一 注册 1 图形如下 2 文字说明 xff08 1 xff09 类图综述 目的 xff1a 让未注册顾
  • 承上的状态机图,又是烂图一副

    1 图形文档如下 2 文字说明 此状态机图反映了系统面向顾客从注册到购物完成的整体的状态变迁以及状态内部发生的事件 xff0c 一共有六个状态 xff0c 状态间转移如上图所示 2 1 ViewItems 中的事件 2 2 Register
  • 让Windows秒变Mac主题,还原度高达99%

    小伙伴们注意 xff1a 公众号的推送机制不再按照时间前后推送了 xff0c 微信公众号信息流乱序 君哥建议大家把科技毒瘤君公众号置顶 xff08 设为星标 xff09 xff0c 以便第一时间看到推送 xff0c 非常感谢 xff0c 方
  • 阿里Arthas(阿尔赛斯)-java诊断工具使用入门

    1 下载官方测试程序启动 doda 64 host166 game curl O https arthas aliyun com math game jar doda 64 host166 game java jar math game j
  • LHL 华为开发者大会有感 之 什么是HMS

    华为移动服务 同义词 HMS xff08 Huawei Mobile Services的英文缩写 xff09 一般指华为移动服务 华为移动服务 xff08 HMS xff09 全称为Huawei Mobile Services xff0c
  • EF Core之自动历史记录

    EF Core之自动历史记录 有的场景下需要记录特定表的增删改操作 xff0c 以便追溯 传统的做法是在增删改的方法里同步做记录 xff0c 很繁琐 在这里我们可以配合EF Core的DBContext做一个全局管控 全局管控自然就要有固定