Fluent NHibernate - смешивание таблиц на подкласс и иерархию таблиц на классы

Дайте следующую структуру,

MyBaseClass {
  public int Id {get; private set;}
}

MySubclassWithDiscriminator : MyBaseClass {
}

MySubclass : MyBaseClass {
  public string SomeThing {get; set;}
}

Как мне использовать Fluent NH для их правильного сопоставления, используя комбинацию таблицы на подкласс и иерархию таблицы на класс? Я пробовал настраивать AutomappingConfiguration, но, похоже, хожу по кругу:

public class AutomappingConfiguration : DefaultAutomappingConfiguration
{
    public override bool ShouldMap(Type type)
    {
        return type.Namespace.Contains("Entities");
    }

    public override bool IsDiscriminated(Type type)
    {
        // only classes with additional properties should be 
        // using the table-per-subclass strategy
        if ((type.IsAssignableFrom(typeof(MyBaseClass)) || 
             type.IsSubclassOf(typeof(MyBaseClass)) && 
             type.GetProperties(BindingFlags.Public | 
                                BindingFlags.FlattenHierarchy)
             .Count() <= 1))
        {
            return true;
        }
        return false;
    }
}

public class SubclassConvention : ISubclassConvention
{
    public void Apply(ISubclassInstance instance)
    {
        // Use the short name of the type, not the full name
        instance.DiscriminatorValue(instance.EntityType.Name);
    }
}

Из моего исследования мне кажется, что использование Дискриминатора - это двоичный выбор при использовании FNH, в то время как HBM может иметь столбец Дискриминатора и подкласс одновременно.


person rbellamy    schedule 20.04.2011    source источник


Ответы (1)


РЕДАКТИРОВАТЬ - 12 мая 2011 г.

Я переписал этот пост, чтобы попытаться ответить на комментарии Джеймса Грегори.

Вот HBM, которого я пытаюсь достичь:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class 
   xmlns="urn:nhibernate-mapping-2.2" 
   name="Mixed_Parent" 
   abstract="true" 
   table="`Mixed_Parent`">
    <id name="Id" type="System.Int32">
      <generator class="identity" />
    </id>
    <discriminator type="String">
      <column name="discriminator" />
    </discriminator>
    <subclass 
     name="Mixed_TPCH_Child" 
     discriminator-value="Mixed_TPCH_Child" />
    <subclass 
     name="Mixed_TPS_Child" 
     discriminator-value="Mixed_TPS_Child">
      <join table="`Mixed_TPS_Child`" >
        <key column="Id" />
        <property name="Description" type="String">
          <column name="Description" />
        </property>
      </join>
    </subclass>
  </class>
</hibernate-mapping>

Итак, что я видел, так это то, что генерируемый HBM является ЛИБО <joined-subclass> или <subclass> без подэлемента <join>, но никогда не является их комбинацией. Я что-то упустил?

Вот неудачный тест, который можно добавить в SubclassPersistenceModelTests, чтобы проиллюстрировать:

namespace MixedTablePerSubclassWithTablePerClassHierarchy
{
    public class Mixed_Parent
    {
        public virtual int Id { get; set; }
    }

    public class Mixed_TPCH_Child
    {

    }

    public class Mixed_TPS_Child
    {
        public virtual string Description { get; set; }
    }

    public class Mixed_ParentMap : ClassMap<Mixed_Parent>
    {
        public Mixed_ParentMap()
        {
            Id(x => x.Id);
            DiscriminateSubClassesOnColumn("discriminator");
        }
    }

    public class Mixed_TPCH_ChildMap : SubclassMap<Mixed_TPCH_Child>
    { }

    public class Mixed_TPS_ChildMap : SubclassMap<Mixed_TPS_Child>
    {
        public Mixed_TPS_ChildMap()
        {
            Map(x => x.Description);
        }
    }
}

[Test]
public void ShouldAllowMixedTablePerSubclassWithTablePerClassHierarchy()
{
    var model = new PersistenceModel();

    model.Add(
        new MixedTablePerSubclassWithTablePerClassHierarchy
            .Mixed_ParentMap());
    model.Add(
        new MixedTablePerSubclassWithTablePerClassHierarchy
            .Mixed_TPCH_ChildMap()
    );
    model.Add(
        new MixedTablePerSubclassWithTablePerClassHierarchy
            .Mixed_TPS_ChildMap());

    var classMapping = model.BuildMappings()
        .First()
        .Classes.First();

    // WHAT SHOULD THIS NUMBER BE (0, 1 or 2)?
    classMapping.Subclasses.Count().ShouldEqual(1);
    classMapping
        .Subclasses
        .First()
        .Type
        .ShouldEqual(
            typeof(
                MixedTablePerSubclassWithTablePerClassHierarchy
                .Mixed_TPS_Child)
        ); // WHICH OF THE CHILDREN WOULD BE FIRST?
}
person rbellamy    schedule 21.04.2011
comment
Я думаю, вы неправильно поняли, что проверяет этот тест; он следит за тем, чтобы лишний элемент <discriminator> не появлялся внутри элемента <subclass>. Ваш HBM ​​тоже этого не делает, поэтому я не понимаю, в чем проблема. Отображение в тесте должно работать так же, как ваш HBM. - person James Gregory; 03.05.2011
comment
Хорошо, я вижу, как я неправильно понял тест, который провозглашаю. Итак, я обновил свою правку, добавив неудачный тест и модель, которые можно добавить в файл SubclassPersistenceModelTests.cs, чтобы проиллюстрировать мое замешательство. - person rbellamy; 08.05.2011
comment
Кстати, какова политика в отношении переписывания вопроса? Я думаю, что смогу прояснить ситуацию, объединив свой первоначальный вопрос с этой попыткой ответа. - person rbellamy; 08.05.2011