开发者

NHibernate mapping table of tables

I'm trying to wrap NHibernate around a legacy database (not created by me). It has what I can best describe as a "table of tables," called TABLE_DETAIL. It looks something like this:

COLUMN_NAME  |  TABLE_VALUE    |  TABLE_DESC
-------------+-----------------+---------------------------------
state        |  CA             |  California
state        |  NY             |  New York
...
countr开发者_StackOverflow中文版y      |  US             |  United States
country      |  CA             |  Canada

I'm trying to map this using Fluent NHibernate with the table-per-class-hierarchy strategy. In other words, I have a TableDetail class, and subclasses State and Country. I use the COLUMN_NAME as the discriminator.

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 thus has a composite key (made up of COLUMN_NAME/TABLE_VALUE), and the discriminator is one of those fields. My problem is that NHibernate expects both components of the composite key to be referenced in another table - but they shouldn't need to be, because one is defined by the discriminator.

For example, I have the ADDRESS_RECORD table:

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

The problem comes in when I try to map my "State" field to my State class. The STATE column in ADDRESS_RECORD refers to half of the TABLE_DETAIL primary key - the TABLE_VALUE part. The COLUMN_NAME part is "state" - because it's the discriminator, I'd expect that it should be provided. But NHibernate doesn't think so, and throws this exception:

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

How can I map this so that NHibernate knows to automatically provide "state" as the value for the second half of the composite key?

If I can provide more information, please let me know.


I came up with a so-so fix. In the base class map (TableDetailMap.cs), where I specified the discriminator, I specified "always select with value", like so:

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

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

Then, in all of the mapping classes that use a TableDetail object, I had to specify to use "select" when fetching, like so:

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

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

    ...snip...
  }
}

This still did not work in the case where I had one of these objects used as part of a composite ID. I'm not sure how to fix that, but I was able to work around it for now.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜