从NHibernate元数据获取类字段名称和表列名称 [英] Getting class field names and table column names from NHibernate metadata

查看:275
本文介绍了从NHibernate元数据获取类字段名称和表列名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景

我正在使用具有各种丑陋角落的遗留数据库.一分是审计.有一个表列出了应该具有审核记录的字段的表名/字段组合.例如,如果存在一个表名带有"WORKORDER",字段名带有"STATUS"的行,那么只要应用程序中的Workorder.Status属性发生更改,我就需要向审计表中添加行.我知道这种方法:NH事件或拦截器,但是在进入那个阶段之前我有一个问题要弄清.

问题

我需要知道的是如何为包含(a)数据库字段名和(b)该类中的相关属性名的单个持久类获取键/值对的列表.因此,对于我的示例,我有一个名为Workorder的类,该类与一个名为(不奇怪)WORKORDER的表相关联.我在该Workorder类上有一个名为CurrentStatus的属性. WORKORDER表中的匹配属性为STATUS.注意属性名称和表列名称之间的不匹配吗?我需要知道属性名称才能访问审核之前和之后的数据.但是我还需要知道支持列的名称,以便查询愚蠢的旧版"AuditTheseColumns"表.

我尝试过的事情

在我的应用程序中,我将Workorder.CurrentStatus从"TS"更改为"IP".我在审核跟踪表中查看,发现WORKORDER.STATUS列已被跟踪.因此,在调用Session.SaveOrUpdate(workorder)之后,我需要找到与STATUS列关联的Workorder属性,并执行Session.Save(auditRecord)来告诉它旧的("TS")值和新的("IP")值. /p>

据我所知,您可以获得有关该类的信息:

        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++;
        }

有关表格的信息:

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

但不能同时进行.有任何想法吗?我不知所措,下一步该去哪里.

解决方案

现在,如果我理解正确,这就是您可以做的....

一种方法是从dll中读取和解析XML映射文件,该DLL会在NHibernate会话工厂建立之前或之后嵌入.这样,您就可以从XML文件中获取所需的所有信息(列对应于哪个属性),并填充一个全局(可能是静态的)自定义对象集合,这些集合将保存实体的名称以及带有属性名称和值的键的字典列名(或相反).

然后您可以按照描述的方式在调用SaveOrUpdate()之后访问此全局集合以获取所需的信息. 这种方法的缺点是您需要编写自己的XML解析逻辑以从XML映射文件中检索所需的信息.

一种替代方法是创建一个自定义属性来装饰实体的每个属性,以获得与每个属性相对应的列名. 一个例子是:

[ColumnName("MyColumn")]
public string Status { get; set; }

使用反射,您可以轻松地获取属性名称,并从属性中获取该属性映射到的列名称.

这种方法的缺点是,当数据库模式更新时,必须使列名与属性值保持同步.

Background

I am using a legacy database with all kinds of ugly corners. One bit is auditing. There is a table listing tablename/field combinations of fields that should have an audit trail. For example, if there is a row that has "WORKORDER" for the table name and "STATUS" for the fieldname, then I need to add row(s) to the auditing table whenever the Workorder.Status property changes in the application. I know the approach: NH events or interceptors, but I've got an issue to figure out before I get to that stage.

Question

What I need to know is how to get a list of key/value pairs for a single persistent class containing (a) the database field name and (b) the associated property name in the class. So for my example, I have a class called Workorder associated with a table called (no surprise) WORKORDER. I have a property on that Workorder class called CurrentStatus. The matching property in the WORKORDER table is STATUS. Notice the mismatch between the property name and table column name? I need to know the property name to access the before and after data for the audit. But I also need to know the backing column name so that I can query the stupid legacy "AuditTheseColumns" table.

What I've tried

in my application I change the Workorder.CurrentStatus from "TS" to "IP". I look in my audit tracking table and see that the WORKORDER.STATUS column is tracked. So after calling Session.SaveOrUpdate(workorder), I need to find the Workorder property associated with the STATUS column and do a Session.Save(auditRecord) telling it the old ("TS") and new ("IP") values.

As far as I can tell, you can get information about the class:

        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++;
        }

And information about the 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);
            }
        }

But not at the same time. Any ideas? I'm at a loss where to look next.

解决方案

Now if I understand correctly here is what you could do....

One way would be to read and parse the XML mapping files from the dll that are embedded before or even after the NHibernate session factory is build. This way you can get all the info you need from the XML files (with column corresponds to which property) and populate a global (probably static) collection of custom objects that will hold the entity's name and a dictionary with key the propery name and value the column name (or the other way around).

You can then access this global collection to get the info you need right after the call to SaveOrUpdate() as you described it. The downside of this approach is that you need to write your own XML parsing logic to retrive the info you need from the XML mapping files.

An alternative would be to create a custom attribute to decorate each property of your entities in order to get the column name that corresponds to each property. An example would be:

[ColumnName("MyColumn")]
public string Status { get; set; }

Using reflection you can easily get the property name and the from the attribute the column name that this property is mapped to.

The downside of this approach would be having to keep in sync your column names with the attribute values when the database schema is updated.

这篇关于从NHibernate元数据获取类字段名称和表列名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆