【问题标题】:Delete trigger for audit table删除审计表的触发器
【发布时间】:2016-11-06 13:50:32
【问题描述】:

我正在开发一个对 SQL Server 数据库中的某个表执行 CRUD 操作的 Web 应用程序。执行这些操作的应用程序中会有一个登录用户。

(顺便说一下,我使用的是实体框架)

假设表格是

我的表

  • MyTableId
  • 某列
  • LastModifiedUserId
  • 最后修改日期

我有一个像

这样的审计表

MyTableHistory

  • MyTableHistoryId
  • MyTableId
  • 某列
  • ActionType --ins/upd/del
  • ActionUserId
  • 行动日期

我正在使用触发器在审计表中插入数据。

通过查阅 Inserted 和 Updated 表来查找修改记录的用户 ID,插入和更新很容易。

但是删除呢?知道如何获取这些信息吗?

【问题讨论】:

  • 如您所说,有INSERTED 伪表,但没有UPDATED 伪表。还有DELETED 伪表
  • 但 DELETED 将仅包含上次更新记录的 LastModifiedUserId,而不是删除记录的人。这就是我想要的
  • suser_sname() 是运行查询的帐户名。
  • suser_sname() 只会返回连接到 SQL Server 的任何帐户的登录信息。如果它被网络服务使用,它不会识别最终用户。

标签: sql-server triggers audit


【解决方案1】:

没有updated 表这样的东西。 DML 触发器中可用的两个伪表是inserteddeleted。在insert 的情况下,deleted 为空,在delete 的情况下,inserted 为空,在update 的情况下,两个表都已填充。
您可以为每个操作创建三个单独的触发器(以区分 ActionType)或尝试将所有触发器组合在一个触发器中。
注意:考虑多行操作。

【讨论】:

    【解决方案2】:

    假设您使用 EF 添加有关哪些用户正在更新记录的信息,捕获该信息的最简单方法是让 EF 对您要删除的数据执行两步过程(更新、删除)。然后,您需要将两个审计行解释为同一操作的一部分。

    有一个更复杂的解决方案“可能”有效,但我还没有测试过。如果您想探索它,下面有更多信息。

    另一种选择是放弃触发器审计(因为这个原因这是有问题的)并改用实体框架。下面是一个如何通过覆盖SaveChanges 方法来实现此目的的示例:

    public virtual IEnumerable<System.Data.Entity.Infrastructure.DbEntityEntry> ChangedEntries()
    {
        return ChangeTracker.Entries().Where(x =>
            x.State == EntityState.Added ||
            x.State == EntityState.Deleted ||
            x.State == EntityState.Modified);
    }
    
    public virtual int SaveChanges(string userName)
    {
        var changes = ChangedEntries();
    
        foreach (var entry in changes)
        {
            var eventType = entry.State == EntityState.Added ? "A" : entry.State == EntityState.Deleted ? "D" : "U";
            var entityType = ObjectContext.GetObjectType(entry.Entity.GetType()).Name;
    
            var oldValues = entry.State == EntityState.Added ? null : JsonConvert.SerializeObject(entry.OriginalValues.ToObject());
            var newValues = entry.State == EntityState.Deleted ? null : JsonConvert.SerializeObject(entry.CurrentValues.ToObject());
    
            oldValues = oldValues?.Substring(0, Math.Min(oldValues.Length, 4000));
            newValues = newValues?.Substring(0, Math.Min(newValues.Length, 4000));
    
            AuditItems.Add(
                new AuditItem
                {
                    EventTime = DateTime.Now,
                    UserName = userName,
                    EntityType = entityType,
                    EventType = eventType,
                    OldValues = oldValues,
                    NewValues = newValues
                }
            );
        }
    
        return base.SaveChanges();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-19
      • 2021-06-05
      • 1970-01-01
      • 1970-01-01
      • 2021-09-05
      • 2013-12-28
      • 1970-01-01
      相关资源
      最近更新 更多