我一直试图让NHibernate ICompositeUserType映射工作。但我一直试图让实现足够通用,以便在不同的表上使用。
我们的遗留数据库有许多纬度和经度表,我想将它们作为Position类映射到我的域对象中。问题是每个表都有不同的纬度和经度列名称。
我已经创建了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
}
}
和位置等级
public class Position
{
public double Latitude { get; private set; }
public double Longitude { get; private set; }
public Position(double latitude, double longitude)
{
Latitude = latitude;
Longitude = longitude;
}
}
我目前有一个可以使用Component流利地图的工作,但这意味着我的Position类必须是可变的,如果不是,我会更喜欢它。
有人可以帮忙吗?我已经好好看了几篇文章和书籍,但我似乎仍然无法让它发挥作用。
谢谢,
亚当
答案 0 :(得分:4)
在映射中添加列名覆盖之前,需要清除Column集合:
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
}
}
如果在添加自定义名称之前未清除列集合,则Fluent NH只会将新列名称附加到用户类型映射的列集合中,这会导致给定用户类型的列太多
如果从流畅的映射生成实际的XML映射(通过在流畅的配置中使用Mappings.ExportTo()),您可能会看到如下内容:
<property <!-- details here -->
<column name="Latitude" />
<column name="Longitude" />
<column name="LPLongitude" />
<column name="LPLatitude" />
</property>
实际应该是:
<property <!-- details here -->
<column name="LPLatitude" />
<column name="LPLongitude" />
</property>
答案 1 :(得分:2)
它不必是可变的,你可以使用私人支持
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
另一种可能性是使用实例化挂钩并在构造函数中使用default(double)
实例化Position类