Nhibernate 在具有不同列名的不同表上使用ICompositeUserType

Nhibernate 在具有不同列名的不同表上使用ICompositeUserType,nhibernate,fluent-nhibernate,Nhibernate,Fluent Nhibernate,我一直在尝试使NHibernate ICompositeUserType映射正常工作。但我一直在努力使实现足够通用,以便在不同的表上使用 我们的传统数据库有许多表,其中纬度和经度为,我想将它们作为一个位置类映射到我的域对象中。问题是每个表的纬度和经度列都有不同的名称 我已经创建了ICompositeUserType的实现,但是我似乎必须将PropertyNames设置为表中列的名称,这意味着我不能在不同的表(具有不同的列名)上使用CustomType 我认为应该将PropertyNames设置为

我一直在尝试使NHibernate ICompositeUserType映射正常工作。但我一直在努力使实现足够通用,以便在不同的表上使用

我们的传统数据库有许多表,其中纬度和经度为,我想将它们作为一个位置类映射到我的域对象中。问题是每个表的纬度和经度列都有不同的名称

我已经创建了ICompositeUserType的实现,但是我似乎必须将PropertyNames设置为表中列的名称,这意味着我不能在不同的表(具有不同的列名)上使用CustomType

我认为应该将PropertyNames设置为Position类中属性的名称,并将它们映射到ClassMap中的表列,但这似乎引发了NHibernate异常:

NHibernate.MappingException: property mapping has wrong number of columns
感觉好像我在映射中做错了什么,但我无法理解

以下是我的ICompositeUserType中的一段代码:

public class PositionUserType : ICompositeUserType
{
  private readonly IType[] _propertyTypes = 
     new [] { NHibernateUtil.Double , NHibernateUtil.Double };

  private readonly string[] _propertyNames = 
     new[] { "Latitude", "Longitude"  };

  public string[] PropertyNames { get { return _propertyNames; } }

  public IType[] PropertyTypes { get { return _propertyTypes; } }

  // Other methods omitted
}
我的班级地图:

public class LastPositionMap : ClassMap<LastPosition>
{
    public LastPositionMap()
    {
        Map(p => p.Position)
            .Columns.Add("LPLongitude", "LPLongitude")
            .CustomType(typeof(PositionUserType));

        // Other mapping omitted
    }
}
我目前有一个可以使用组件fluent映射的工作,但这意味着我的Position类必须是可变的,如果不是,我更喜欢它

有人能帮忙吗?我已经仔细阅读了几篇文章和几本书,但我似乎仍然无法使它发挥作用

谢谢


Adam

在映射中添加列名替代之前,需要清除列集合:

public class LastPositionMap : ClassMap<LastPosition>
{
    public LastPositionMap()
    {
        Map(p => p.Position)

            // Clear the columns to get rid of Fluent NH's default column names
            .Columns.Clear()

            .ColumnsAdd("LPLongitude", "LPLongitude")
            .CustomType(typeof(PositionUserType));

        // Other mapping omitted
    }
}
公共类LastPositionMap:ClassMap
{
公共位置图()
{
地图(p=>p.Position)
//清除列以删除Fluent NH的默认列名
.Columns.Clear()
.ColumnsAdd(“LPLongitude”、“LPLongitude”)
.CustomType(typeof(PositionUserType));
//省略其他映射
}
}
如果在添加自定义名称之前没有清除列集合,Fluent NH只会将新列名附加到用户类型映射的列集合中,这会导致给定用户类型的列过多

如果从fluent映射生成实际的XML映射(通过在fluent配置中使用mappings.ExportTo()),您可能会看到如下内容:

<property <!-- details here -->
  <column name="Latitude" /> 
  <column name="Longitude" /> 
  <column name="LPLongitude" /> 
  <column name="LPLatitude" /> 
</property>


它不必是可变的,您可以使用私有backingfield

Component(x => x.Position, c =>
    {
        c.Map(p => p.Longitude, "LPLongitude").Access.BackingField();
        c.Map(p => p.Latitude, "LPLatitude").Access.BackingField();
    })
唯一需要的是为usercode看不到的类提供一个无参数构造函数

protected Position() { } // to make NHibernate default implementation happy

另一种可能是使用实例化钩子,在构造函数中用
default(double)
实例化Position类,该类与您发布的问题相同,用FNH清除映射没有帮助,HBM文件看起来是正确的。
Component(x => x.Position, c =>
    {
        c.Map(p => p.Longitude, "LPLongitude").Access.BackingField();
        c.Map(p => p.Latitude, "LPLatitude").Access.BackingField();
    })
protected Position() { } // to make NHibernate default implementation happy