J'utilise une base de données existante avec toutes sortes de coins laids. Un bit est l'audit. Il existe un tableau répertoriant les combinaisons nom de table/champ des champs qui doivent avoir une trace d'audit. Par exemple, si une ligne contient "WORKORDER" pour le nom de table et "STATUS" pour le nom de champ, j'ai besoin d'ajouter des lignes à la table d'audit lorsque la propriété Workorder.Status change dans l'application. Je connais l'approche: les événements NH ou les intercepteurs, mais j'ai un problème à résoudre avant d'arriver à ce stade.
Question
Ce que je dois savoir est comment obtenir une liste de paires clé/valeur pour une seule classe persistante contenant (a) le nom du champ de base de données et (b) le nom de propriété associé au classe. Donc pour mon exemple, j'ai une classe appelée Workorder associée à une table appelée (pas de surprise) WORKORDER. J'ai une propriété sur cette classe Workorder appelée CurrentStatus. La propriété correspondante dans la table WORKORDER est STATUS. Notez l'incompatibilité entre le nom de la propriété et le nom de la colonne de la table? J'ai besoin de connaître le nom de la propriété pour accéder aux données avant et après pour l'audit. Mais j'ai aussi besoin de connaître le nom de la colonne de sauvegarde pour que je puisse interroger le stupide tableau "AuditTheseColumns".
Ce que j'ai essayé
dans ma demande que je change la Workorder.CurrentStatus de "TS" à "IP". Je regarde dans ma table de suivi d'audit et vois que la colonne WORKORDER.STATUS est suivie. Donc après avoir appelé Session.SaveOrUpdate (workorder), je dois trouver la propriété Workorder associée à la colonne STATUS et faire un Session.Save (auditRecord) en lui disant les anciennes ("TS") et nouvelles ("IP") valeurs.
Pour autant que je peux dire, vous pouvez obtenir des informations sur la classe:
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++;
}
et des informations sur la table:
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);
}
}
Mais pas en même temps. Des idées? Je ne sais plus où regarder.
Ce n'est pas directement lié à votre question, mais cela pourrait être une idée - pourquoi ne pas auditer les changements au niveau de l'objet au lieu de la base de données? Les utilisateurs finaux traitent l'objet .NET au niveau de l'interface utilisateur et parce que les objets de données .NET ne reflètent pas uniquement les objets de la base de données (tableaux, vues ...), il est peut-être plus précis d'auditer les événements sur les objets. ceux Qu'est-ce que tu penses? – Leo
Si cela ne tenait qu'à moi, je verrais certainement ce type d'approche. Malheureusement, je travaille avec une base de données qui se cache derrière un produit bien établi et je ne peux pas contourner leur approche de l'audit. Alors oui, je souhaite! Mais hélas, pas une approche viable pour ce projet. – Dylan
Pour moi; J'ai décidé d'utiliser des constantes pour stocker les noms des tables et le nom de la colonne clé; puis j'utilise la constante dans les fichiers de mappage nhibernate et tsql – kite