【问题标题】:Using ICompositeUserType on different tables with different column names在具有不同列名的不同表上使用 ICompositeUserType
【发布时间】:2013-02-28 00:54:21
【问题描述】:

我一直在尝试让 NHibernate ICompositeUserType 映射工作。但我坚持尝试使实现足够通用以在不同的表上使用。

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

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

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

NHibernate.MappingException: property mapping has wrong number of columns

感觉好像我在映射中做错了什么,但我无法弄清楚。

这是来自我的 ICompositeUserType 的一个 sn-p 代码:

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 fluent map 的工作,但这意味着我的 Position 类必须是可变的,如果不是,我更喜欢它。

有人可以帮忙吗?我已经很好地查看了几篇文章和书籍,但我似乎仍然无法让它发挥作用。

谢谢,

亚当

【问题讨论】:

  • 遇到与您发布的问题相同的问题,使用 FNH 清除映射没有帮助,HBM 文件看起来正确。

标签: nhibernate fluent-nhibernate


【解决方案1】:

在映射中添加列名覆盖之前,您需要清除 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>

【讨论】:

    【解决方案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 类

    【讨论】:

      猜你喜欢
      • 2012-05-20
      • 2013-04-09
      • 2013-05-18
      • 2021-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多