2016-07-04 7 views
1

Ich arbeite an einer Webanwendung, die CRUD-Vorgänge an einer Tabelle in einer SQL Server-Datenbank ausführt. In der Anwendung, die diese Vorgänge ausführt, wird ein Benutzer protokolliert.Auslöser für Audit-Tabelle löschen

(By the way, ich Entity Framework)

Lasst uns sagen Tisch

MyTable

  • MyTableId
  • SomeColumn
  • LastModifiedUserId
  • LastModifiedDate ist

Und ich habe eine eine Audit-Tabelle wie

MyTableHistory

  • MyTableHistoryId
  • MyTableId
  • SomeColumn
  • Action --ins/upd/del
  • ActionUserId
  • ActioDate

Und ich bin mit Trigger-Daten auf die Audit-Tabelle einzufügen.

Einfügungen und Aktualisierungen sind einfach, indem Sie die Tabellen Eingefügt und Aktualisiert konsultieren, um die Benutzer-ID zu finden, die den Datensatz geändert hat.

Aber was ist mit Löschungen? Irgendeine Idee, wie ich diese Info bekommen könnte?

+0

gibt es die 'INSERTED' Pseudo-Tabelle, wie Sie gesagt haben, aber keine' UPDATED' ein. Es gibt auch die "DELETED" Pseudo-Tabelle – Lamak

+0

Aber DELETED wird einfach die LastModifiedUserId haben, die den Datensatz zuletzt aktualisiert hat, nicht die, die den Datensatz gelöscht hat. Das ist der, den ich will – DJPB

+0

'suser_sname()' ist der Name des Kontos, die die Abfrage ausführen. –

Antwort

0

Es gibt keine updated Tabelle. Die zwei in DML-Triggern verfügbaren Pseudo-Tabellen sind inserted und deleted. Bei insert ist die Tabelle deleted leer, bei delete ist die Tabelle inserted leer, bei update sind beide Tabellen belegt.
Sie können drei separate Trigger für jede Aktion erstellen (um zwischen ActionType zu unterscheiden) oder versuchen, alle in einem Trigger zu kombinieren.
Hinweis: mehrere Zeilenaktionen berücksichtigen.

0

Angenommen, Sie verwenden EF, um Informationen darüber hinzuzufügen, welcher Benutzer Datensätze aktualisiert, ist der einfachste Weg, diese Informationen zu erfassen, dass EF einen zweistufigen Prozess (UPDATE, DELETE) für die Daten ausführt, die Sie löschen möchten. Sie müssen dann die beiden Audit-Zeilen als Teil derselben Operation interpretieren.

Es gibt eine viel kompliziertere Lösung, die "könnte" funktionieren, aber ich habe es nicht getestet. Untenstehend finden Sie weitere Informationen, wenn Sie diese erkunden möchten.

Eine weitere Option ist insgesamt Auslöser Revision zu verzichten (die aus diesem Grund problematisch ist) und stattdessen Entity Framework verwenden. Unten ist ein Beispiel dafür, wie man dies durch Überschreiben der SaveChanges Methode erreichen könnte:

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(); 
}