HintergrundErste-Klasse-Feldnamen und Tabellenspaltennamen von NHibernate Metadaten
ich mit allen Arten von hässlichen Ecken eines Vermächtnis Datenbank verwenden. Ein bisschen ist Auditing. Es gibt eine Tabelle, die Tabellenname/Feldkombinationen von Feldern auflistet, die einen Audit-Trail haben sollten. Wenn beispielsweise eine Zeile mit dem Namen "WORKORDER" für den Tabellennamen und "STATUS" für den Feldnamen vorhanden ist, muss ich der Überwachungstabelle immer dann Zeilen hinzufügen, wenn sich die Eigenschaft "Workorder.Status" in der Anwendung ändert. Ich kenne den Ansatz: NH-Ereignisse oder Abfangjäger, aber ich habe ein Problem, bevor ich zu diesem Zeitpunkt komme.
Frage
Was ich wissen muss, ist, wie für eine einzige persistente Klasse eine Liste von Schlüssel/Wert-Paare zu erhalten, die (a) die Datenbank Feldnamen und (b) die zugehörige Eigenschaftsnamen in der Klasse. Also für mein Beispiel habe ich eine Klasse namens Workorder, die mit einer Tabelle namens (keine Überraschung) WORKORDER verbunden ist. Ich habe eine Eigenschaft in dieser Workorder-Klasse namens CurrentStatus. Die übereinstimmende Eigenschaft in der Tabelle WORKORDER ist STATUS. Beachten Sie, dass der Name der Eigenschaft und der Name der Tabellenspalte nicht übereinstimmen. Ich muss den Namen der Eigenschaft kennen, um auf die Vorher-Nachher-Daten für die Prüfung zugreifen zu können. Aber ich muss auch den Namen der Backing-Spalte kennen, damit ich die dumme Tabelle "AuditTheseColumns" abfragen kann.
Was ich versucht habe
in meiner Anwendung ändern Sie den Workorder.CurrentStatus von "TS" auf "IP". Ich schaue in meine Überwachungsverfolgungstabelle und sehe, dass die Spalte WORKORDER.STATUS verfolgt wird. Nach dem Aufruf von Session.SaveOrUpdate (Arbeitsauftrag) muss ich die Arbeitsorder-Eigenschaft suchen, die der STATUS-Spalte zugeordnet ist, und eine Session.Save (auditRecord) ausführen, die den alten ("TS") und neuen ("IP") Wert angibt.
var fieldNames = new List<string>();
IClassMetadata classMetadata = SessionFactory(Resources.CityworksDatasource).GetClassMetadata(typeof(T));
int propertyCount = 0;
foreach (IType propertyType in classMetadata.PropertyTypes)
{
if (propertyType.IsComponentType)
{
var cp = (ComponentType)propertyType;
foreach (string propertyName in cp.PropertyNames)
{
fieldNames.Add(propertyName);
}
}
else if(!propertyType.IsCollectionType)
{
fieldNames.Add(classMetadata.PropertyNames[propertyCount + 1]);
}
propertyCount++;
}
Und Informationen über die Tabelle:
var columnNames = new List<string>();
PersistentClass mappingMeta = ConfigureCityworks().GetClassMapping(typeof(T));
foreach (Property property in mappingMeta.PropertyIterator)
{
foreach (Column selectable in property.ColumnIterator)
{
if (columnNames.Contains(selectable.Name)) continue;
columnNames.Add(selectable.Name);
}
}
aber nicht zugleich
Soweit ich das beurteilen kann, können Sie Informationen über die Klasse erhalten. Irgendwelche Ideen? Ich weiß nicht, wo ich als nächstes hinsehen soll.
Diese nicht direkt auf Ihre Frage bezieht sich aber Es könnte eine Idee sein - warum auditieren Sie Änderungen nicht auf Objektebene statt auf Datenbank? Endbenutzer haben mit .NET-Objekten auf UI-Ebene zu tun, und weil .NET-Datenobjekte nicht nur eine 1: 1-Spiegelung von Datenbankobjekten (Tabellen, Ansichten ...) sind, ist es vielleicht genauer, Ereignisse auf .NET-Objekten anstatt auf Datenbank zu überwachen Einsen. Was denken Sie? – Leo
Wenn es nach mir ginge, würde ich definitiv auf diese Art von Ansatz schauen. Leider arbeite ich mit einer Datenbank, die hinter einem gut etablierten Produkt sitzt, und ich kann ihren Ansatz zum Auditing nicht umgehen. Also ja, ich wünsche! Aber leider kein praktikabler Ansatz für dieses Projekt. – Dylan
Für mich; Ich entschied mich, Konstanten zu verwenden, um die Tabellennamen und Schlüsselspaltennamen zu speichern; dann verwende ich die Konstante in den Nhibernate-Mapping-Dateien und rohen tsql – kite