我正在开发一个在SQL Server数据库中的某些表上执行CRUD操作的Web应用程序。应用程序中将有一个记录用户执行这些操作。
(顺便说一下,我正在使用实体框架)
假设表格是
MyTable的
我有一个像
这样的审计表MyTableHistory
我正在使用触发器在审计表上插入数据。
通过查阅Inserted和Updated表来查找修改记录的用户ID,可以轻松进行插入和更新。
但是删除呢?知道如何获得这些信息吗?
答案 0 :(得分:0)
没有updated
表这样的东西。 DML触发器中可用的两个伪表是inserted
和deleted
。在insert
表deleted
为空的情况下,如果delete
表inserted
为空,则在update
的情况下填充两个表。
您可以为每个操作创建三个单独的触发器(以区分ActionType
)或尝试将所有操作组合在一个触发器中
注意:考虑多行操作。
答案 1 :(得分:0)
假设您使用EF添加有关哪个用户正在更新记录的信息,捕获该信息的最简单方法是让EF对您要删除的数据执行两步处理(UPDATE,DELETE)。然后,您需要将两个审计行解释为同一操作的一部分。
有一个更复杂的解决方案“可能”有效,但我还没有测试过。如果您想探索它,可以在下面找到更多信息。
另一个选择是放弃触发审计(由于这个原因,这是有问题的)并改为使用实体框架。下面是一个如何通过覆盖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();
}