AntecedentesConseguir nombres de los campos de clase y los nombres de columna de la tabla de metadatos NHibernate
Estoy utilizando una base de datos heredada con todo tipo de rincones feos. Un bit es auditar. Hay una tabla que enumera las combinaciones nombre de tabla/campo de campos que deberían tener una pista de auditoría. Por ejemplo, si hay una fila que tiene "WORKORDER" para el nombre de la tabla y "STATUS" para el nombre del campo, entonces necesito agregar fila (s) a la tabla de auditoría siempre que la propiedad Workorder.Status cambie en la aplicación. Conozco el enfoque: eventos NH o interceptores, pero tengo un problema que resolver antes de llegar a esa etapa.
Pregunta
Lo que necesito saber es cómo conseguir una lista de pares clave/valor para una sola clase persistente que contiene (a) el nombre del campo de base de datos y (b) el nombre de la propiedad asociada en el clase. Entonces, para mi ejemplo, tengo una clase llamada Workorder asociada con una tabla llamada (sin sorpresa) WORKORDER. Tengo una propiedad en esa clase Workorder llamada CurrentStatus. La propiedad coincidente en la tabla WORKORDER es STATUS. ¿Observe la discrepancia entre el nombre de la propiedad y el nombre de la columna de la tabla? Necesito saber el nombre de la propiedad para acceder a los datos de antes y después de la auditoría. Pero también necesito saber el nombre de la columna de respaldo para poder consultar la estúpida tabla heredada "AuditTheseColumns".
Lo que he tratado
en mi aplicación puedo cambiar el Workorder.CurrentStatus de "TS" a "IP". Miro en mi tabla de seguimiento de auditoría y veo que se realiza un seguimiento de la columna WORKORDER.STATUS. Entonces, después de llamar a Session.SaveOrUpdate (workorder), necesito encontrar la propiedad Workorder asociada con la columna STATUS y hacer una Session.Save (auditRecord) diciéndole los valores antiguos ("TS") y nuevos ("IP").
Por lo que yo puedo decir, se puede obtener información acerca de la clase:
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++;
}
y la información sobre la mesa:
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);
}
}
Pero no al mismo tiempo. ¿Algunas ideas? No puedo mirar a continuación.
Esto no está directamente relacionada con su pregunta, pero podría ser una idea: ¿por qué no auditas los cambios en el nivel de objeto en lugar de en la base de datos? Los usuarios finales tratan con el objeto .NET en el nivel UI y como los objetos de datos .NET no son solo reflejos 1: 1 de objetos de base de datos (tablas, vistas ...) quizás sea más preciso auditar eventos en objetos .NET en lugar de bases de datos unos. ¿Qué piensas? – Leo
Si dependiera de mí definitivamente estaría buscando ese tipo de enfoque. Desafortunadamente, estoy trabajando con una base de datos que se encuentra detrás de un producto bien establecido y no puedo eludir su enfoque de auditoría. Entonces sí, ¡ojalá! Pero, por desgracia, no es un enfoque viable para este proyecto. – Dylan
Para mí; Decidí usar constantes para almacenar los nombres de las tablas y el nombre de la columna clave; luego utilizo la constante en los archivos de mapeo nhibernate y tsql en bruto – kite