C# NHibernate IUserType获取映射的属性名称

C# NHibernate IUserType获取映射的属性名称,c#,.net,nhibernate,fluent-nhibernate,C#,.net,Nhibernate,Fluent Nhibernate,我们正在进行一个NHibernate项目,需要实现NHibernateIUserType接口。所以我们做到了,到目前为止,它运行良好(我们还没有开始测试NullSafeSet方法)。但是,我们有一个问题:我们需要知道映射的是什么属性,以便能够返回正确的结果 情况: 我们需要映射的值作为int存储在数据库中,我们需要根据该值创建一个code对象。为了能够创建代码对象,我们需要一个字符串以及前面提到的int。此字符串是我们映射的属性的名称 我已经发现names参数包含属性的NHibernate SQ

我们正在进行一个NHibernate项目,需要实现NHibernate
IUserType
接口。所以我们做到了,到目前为止,它运行良好(我们还没有开始测试
NullSafeSet
方法)。但是,我们有一个问题:我们需要知道映射的是什么属性,以便能够返回正确的结果

情况: 我们需要映射的值作为
int
存储在数据库中,我们需要根据该值创建一个code对象。为了能够创建代码对象,我们需要一个字符串以及前面提到的int。此
字符串
是我们映射的属性的名称

我已经发现
names
参数包含属性的NHibernate SQL别名(它的形式是:“IS69_6_”),但我不知道该值是否保持不变(在调试时,它似乎保持不变)

一些代码需要澄清: CodeTypeMapper.cs

公共类代码类型映射器:IUserType
{
公共新布尔等于(对象x、对象y)
{
返回x!=null&&x.Equals(y);
}
公共int GetHashCode(对象x)
{
返回x.GetHashCode();
}
/**********与问题有关的守则:**********/
公共对象NullSafeGet(IDataReader rs,字符串[]名称,对象所有者)
{
var key=(int?)NHibernateUtil.Int32.NullSafeGet(rs,names[0]);
如果(key==null)返回null;
//所以这里我们需要能够得到正确的代码。
//为了获得正确的代码,我们需要密钥(在上面获取)
//但我们还需要映射的属性的名称
//在本例中有一个虚拟值。
Code Code=MasterMetaProvider.MasterMeta.GetCode(“PropertyName”,(int)键);
if(code==null)返回null;
//现在我们有了Code对象,我们可以使用它返回正确的结果
var result=newnetworkobjectenum((int)键,code.codedescn);
返回结果;
}
/***************************************************/
public void NullSafeSet(IDbCommand cmd,对象值,int索引)
{
如果(值==null)
{
NHibernateUtil.Int32.NullSafeSet(cmd,null,index);
}
其他的
{
value=int.Parse(value.ToString());
NHibernateUtil.Int32.NullSafeSet(cmd,value,index);
}
}
公共对象深度复制(对象值)
{
返回值;
}
公共对象替换(对象原始、对象目标、对象所有者)
{
归还原件;
}
公共对象集合(对象缓存,对象所有者)
{
返回缓存;
}
公共对象(对象值)
{
返回值;
}
公共SqlType[]SqlTypes
{
得到
{
var-types=new-SqlType[1];
types[0]=新的SqlType(DbType.String);
返回类型;
}
}
公共类型返回类型
{
获取{return typeof(NetworkObjectEnum);}
}
公共布尔可换
{
获取{return false;}
}
}
NHibernate映射代码:

//我们需要此属性的名称
映射(x=>x.PropertyName).Column(“PropertyNameInDB”).CustomType();

问题: 所以我想问的问题是:是否可以在
CodeTypeMapper
类中访问上述属性的名称

提前谢谢

问候,, 亚尼克·塞勒曼斯


2013年9月23日更新: 为了澄清我的问题,我将举一个例子:假设有一个代码表指定城市、交通类型等:

+----+-----------+------------+-----------+
| id | code_type | code_value | code_desc |
+----+-----------+------------+-----------+
|  1 | city      |          5 | Antwerp   |
|  2 | city      |          8 | Brussels  |
|  3 | city      |          1 | Ghent     |
|  4 | transport |          1 | boat      |
|  5 | transport |          8 | plane     |
|  6 | transport |          9 | car       |
+----+-----------+------------+-----------+
接下来,我们有一个旅行表,它以以下方式使用此代码表:

+----+------+-------------------+-----------+
| id | city |   other_column    | transport |
+----+------+-------------------+-----------+
|  1 |    5 | some random value |         1 |
|  2 |    8 | randomness        |         8 |
|  3 |    1 | a value           |         9 |
+----+------+-------------------+-----------+
如您所见:如果我们想知道代码的描述,我们可以通过查看列名和旅行表中该列中的值来知道需要从代码表中获取什么值

c#class
Travel
可能看起来像这样:

public abstract Class CodeTableBase
{
    public virtual int Id { get; protected set; }
    public virtual string CodeType { get; protected set; }
    public virtual int Value { get; protected set; }
    public virtual string Description { get; protected set; }
}

public class City : CodeTableBase {}

public abstract class CodeTableMap<T> : ClassMap<T> where T : CodeTableBase
{
    public CodeTableMap() 
    {
        Table("CodeTable");
        Id(x => Id, "id").your id generation strategy
        CodeType(x => x.CodeType, "code_type");
        Value(x => x.Value, "code_value");
        Description(x => x.Description, "code_description");
    }

    public CodeTableMap(string codeType) : this()
    {
        Where("code_type = '" + codeType + '"); // may need to use property name
    }
}

public class CityMap : CodeTableMap<City>
{
    public CityMap : base("city") {}
}
公务舱旅行
{
公共int Id{get;set;}
公共int城市{get;set;}
公共字符串OtherColumn{get;set;}
公共int传输{get;set;}
}

因此,我的问题是:在映射Travel类时,是否可以在运行时在
IUserType
实现中获取属性名称“city”,以便能够从代码表中获取正确的值?(注意:我无法更改DB设计。)

我不确定你的意思,但也许你需要这样的东西:

public abstract Class CodeTableBase
{
    public virtual int Id { get; protected set; }
    public virtual string CodeType { get; protected set; }
    public virtual int Value { get; protected set; }
    public virtual string Description { get; protected set; }
}

public class City : CodeTableBase {}

public abstract class CodeTableMap<T> : ClassMap<T> where T : CodeTableBase
{
    public CodeTableMap() 
    {
        Table("CodeTable");
        Id(x => Id, "id").your id generation strategy
        CodeType(x => x.CodeType, "code_type");
        Value(x => x.Value, "code_value");
        Description(x => x.Description, "code_description");
    }

    public CodeTableMap(string codeType) : this()
    {
        Where("code_type = '" + codeType + '"); // may need to use property name
    }
}

public class CityMap : CodeTableMap<City>
{
    public CityMap : base("city") {}
}


实现IPParameterizedType您可以在映射属性名称时发送:

Fluent NHibernate不提供此功能,但您可以使用xml文件


其他不太优雅的解决方案:

var propertyName = GetPropertyName(owner.GetType(), owner, typeof(YourAttribute));

public static string GetPropertyName(Type entityType, object entity, Type attributeType)
{
    if (entity == null) return null;

    var propertyInfo = GetPropertyInfo(entityType, attributeType);

    return propertyInfo == null ? null : propertyInfo.Name;
}

public static PropertyInfo GetPropertyInfo(Type entityType, Type attributeType)
{
    return entityType.GetProperties().FirstOrDefault(prop => prop.GetCustomAttributes(false)
        .Count(x => x.GetType() == attributeType) > 0);
}
这种设计被称为“神桌”,我很同情你。我刚开始的时候,我们的主要产品就有这样一个,我花了一年时间使它正常化

在重构之前,我通过使用视图对其进行虚拟规范化,将其映射到NHibernate。也就是说,为城市、交通等创建一个视图,并将其映射为表。我知道您不能更改模式,但是如果您可以添加视图,这是一个很好的解决方案

备选方案1:为代码表中的每种类型创建IUserType实现

备选方案2:在使用视图之前,我使用了NHibernate向映射中添加where子句的功能。我记得这种方法有缺点,我认为其中一个缺点是where子句在查询中并不总是像预期的那样应用。使用Fluent NHibernate,映射将如下所示:

public abstract Class CodeTableBase
{
    public virtual int Id { get; protected set; }
    public virtual string CodeType { get; protected set; }
    public virtual int Value { get; protected set; }
    public virtual string Description { get; protected set; }
}

public class City : CodeTableBase {}

public abstract class CodeTableMap<T> : ClassMap<T> where T : CodeTableBase
{
    public CodeTableMap() 
    {
        Table("CodeTable");
        Id(x => Id, "id").your id generation strategy
        CodeType(x => x.CodeType, "code_type");
        Value(x => x.Value, "code_value");
        Description(x => x.Description, "code_description");
    }

    public CodeTableMap(string codeType) : this()
    {
        Where("code_type = '" + codeType + '"); // may need to use property name
    }
}

public class CityMap : CodeTableMap<City>
{
    public CityMap : base("city") {}
}
公共抽象类代码表库
{
公共虚拟整数Id{get;protected set;}
公共虚拟字符串代码类型{get;protected set;}
公共虚拟int值{get;protected set;}
P