Как достичь таблицы для конкретного класса, когда базовый класс является абстрактным в беглом nhibernate? - PullRequest
9 голосов
/ 12 сентября 2011

у меня следующий сценарий

public abstract class BaseClass
{
  public virtual int Id {get; set};
  public virtual string Name {get; set;}
}

public class FirstSubClass : BaseClass
{
   //properties and behaviour here
}

public class SecondSubClass : BaseClass
{
  //properties of SecondSubclass Here
}

public class ProcessStep
{
   public virtual IList<BaseClass> ContentElements {get; set;}  
}

для отображения я использовал следующий фрагмент кода: -

this._sessionFactory =
                          Fluently.Configure().Database(SQLiteConfiguration.Standard
                          .ConnectionString(@"Data Source=SqliteTestSqlDataAccess.s3db;    Version=3; New=True; Pooling=True; Max Pool Size=1;"))
                          .Mappings(m => m.AutoMappings.Add(AutoMap.Assembly(assemblyWithDomainClasses).Conventions.Add(DefaultCascade.All())))
                          .ExposeConfiguration(BuildSchema)
                          .BuildSessionFactory();

По умолчанию свободный будет игнорировать абстрактный базовый класс, который является BaseClass. Но так как в классе ProcessStep есть свойство ContentElements, которое возвращает IList , я получаю исключение: - NHibernate.MappingException: ассоциация ссылается на несопоставленный класс: BaseClass

Если я включаю базовый класс, используя IncludeBase (typeof (BaseClass)), то он работает нормально, но создает таблицу для классов BaseClass и Derived, а записи связываются с помощью отношения FK-PK ( таблица для подкласса *). 1014 *). То, чего я хочу достичь, это таблица для конкретного класса . то есть каждый производный класс будет иметь свою собственную таблицу, в которой будут все свойства производного класса + свойства базового класса. Есть идеи, как этого добиться?

Ответы [ 2 ]

9 голосов
/ 29 сентября 2011

Так как я не видел ваше отображение, позвольте мне предоставить мое. Вы можете добиться этого, сделав так

public class BaseClassMap:ClassMap<BaseClass>
{
    public BaseClassMap()
    {
        /*
         * Identity generator can't be native because subclass objects should be unique
         * So use HiLo or Guid or other generators which will generate unique id on the child tables
         */
        Id(x => x.Id).GeneratedBy.Guid(); 
        Map(x => x.Name);
        UseUnionSubclassForInheritanceMapping(); // This is important - uses union-subclass mappings for the derived classes
    }
}

public class FirstSubClassMap : SubclassMap<FirstSubClass>
{
    public FirstSubClassMap()
    {
        Table("FirstSubClassTable");
        // Map properties for FirstSubClass
    }
}

public class SecondSubClassMap : SubclassMap<SecondSubClass>
{
    public SecondSubClassMap()
    {
        Table("SecondSubClassTable");
        // Map properties for SecondSubClass
    }
}
1 голос
/ 17 октября 2017

Это вызвало у меня головную боль от реализации стратегии наследования «Таблица на конкретный класс» с абстрактным базовым классом с автоматическим отображением nhibernate. Но я думаю, что наконец нашел решение и хочу поделиться им с вами. Я также думаю, что он не добавлен в документы по автоматическому созданию, потому что он может рассматриваться как «слабый» дизайн базы данных.

Сначала вот несколько ресурсов, которые я нашел по этой теме:

Эти ресурсы в основном описывают, как вам нужно это сделать:

  1. Как вы уже упоминали, беглый nhibernate игнорирует абстрактные базовые классы. Поэтому вам нужно добавить их явно.
// abstractBaseTypes is just a simple enumeration of base types
// model is the AutoPersistenceModel
abstractBaseTypes.ForEach(m => model = model.IncludeBase(m));
  1. a) Если вы знаете абстрактные базовые типы во время компиляции, вы можете использовать
//sets the union subclass strategy for the known base model
model.Override<SuperType>(m => m.UseUnionSubclassForInheritanceMapping()))
  1. b) Если вы не знаете конкретные типы, вы можете создать переопределение сопоставления для каждого базового типа:
public class AbstractRightEntryMappingOverride : IAutoMappingOverride<AbstractRightEntry>
{
    public void Override(AutoMapping<AbstractRightEntry> mapping)
    {
        mapping.UseUnionSubclassForInheritanceMapping();
    }
}

// You need to tell nhibernate where to find the overriden mappings. 
// You simply can add the assemblies again.
modelAssemblies.ForEach(a => model = model.UseOverridesFromAssembly(a));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...