NHibernate表的映射表

时间:2011-01-25 14:02:24

标签: .net fluent-nhibernate

我正在尝试将NHibernate包装在遗留数据库周围(不是由我创建的)。它有我最能描述的“表格表”,称为TABLE_DETAIL。它看起来像这样:

COLUMN_NAME  |  TABLE_VALUE    |  TABLE_DESC
-------------+-----------------+---------------------------------
state        |  CA             |  California
state        |  NY             |  New York
...
country      |  US             |  United States
country      |  CA             |  Canada

我正在尝试使用Fluent NHibernate和每个类的层次结构策略来映射它。换句话说,我有一个TableDetail类,子类是State和Country。我使用COLUMN_NAME作为鉴别器。

TableDetailMap.cs:

public class TableDetailMap : ClassMap<TableDetail>
{
  public TableDetailMap()
  {
    Table("TABLE_DETAIL");
    CompositeId()
      .KeyProperty(x => x.TableValue, "TABLE_VALUE")
      .KeyProperty(x => x.ColumnName, "COLUMN_NAME");
    Map(x => x.ColumnName).Column("COLUMN_NAME");
    Map(x => x.TableDesc).Column("TABLE_DESC");
    DiscriminateSubClassesOnColumn("COLUMN_NAME");
  }
}

StateMap.cs:

public class StateMap : SubclassMap<State>
{
  public StateMap()
  {
    DiscriminatorValue("state");
  }
}
因此,TABLE_DETAIL具有复合键(由COLUMN_NAME / TABLE_VALUE组成),并且鉴别符是这些字段之一。我的问题是NHibernate期望在另一个表中引用复合键的两个组件 - 但它们不应该是,因为一个是由鉴别器定义的。

例如,我有ADDRESS_RECORD表:

LINE_1           |  CITY           |  STATE    |  ZIP
-----------------+-----------------+-----------+----------------
123 Any Street   |  Anytown        |  CA       |  12345

当我尝试将“State”字段映射到我的State类时,会出现问题。 ADDRESS_RECORD中的STATE列引用TABLE_DETAIL主键的一半 - TABLE_VALUE部分。 COLUMN_NAME部分是“状态” - 因为它是鉴别器,我希望它应该被提供。但NHibernate并不这么认为,并抛出了这个例外:

Foreign key (FK3D33E87CA66E339C:ADDRESS_RECORD [STATE])) must have same number of columns as the referenced primary key (TABLE_DETAIL [TABLE_VALUE, COLUMN_NAME])

我如何映射这个以便NHibernate知道自动提供“状态”作为复合键的后半部分的值?

如果我能提供更多信息,请告诉我。

1 个答案:

答案 0 :(得分:0)

我想出了一个马马虎虎的修复方法。在我指定鉴别器的基类映射( TableDetailMap.cs )中,我指定了“总是选择值”,如下所示:

public class TableDetailMap : ClassMap<TableDetail>
{
  public TableDetailMap()
  {
    ...snip...

    DiscriminateSubClassesOnColumn("COLUMN_NAME").AlwaysSelectWithValue();
  }
}

然后,在所有使用 TableDetail 对象的映射类中,我必须指定在获取时使用“select”,如下所示:

public class AddressRecordMap : ClassMap<AddressRecord>
{
  public AddressRecordMap()
  {
    ...snip...

    References(x => x.State)
      .Column("STATE")
      .Fetch.Select();

    ...snip...
  }
}

在我将其中一个对象用作复合ID的一部分的情况下,这仍然不起作用。我不知道如何解决这个问题,但我现在能够解决这个问题。