NHibernate: Объект с идентификатором не относится к указанному подклассу: (загружаемый объект был неправильного класса) - PullRequest
2 голосов
/ 10 августа 2010

Я получаю ошибку ниже:

Объект с идентификатором: 34dd93d3-374e-df11-9667-001aa03fa2c4 не относится к указанному подклассу: MyNamespace.ClassA (загружаемый объект был неправильного класса [MyNamespace.ClassB1])

Стек вызовов:

в NHibernate.Loader.Loader.InstanceAlreadyLoaded (IDataReader rs, Int32 i, IEntityPersister persister, ключ EntityKey, объект obj, LockMode lockMode, сеанс ISessionImplementor)
в NHibernate.Loader.Loader.GetRow (IDataReader rs, постоянные ILoadable [], ключи EntityKey [], необязательный объект ObjectObject, необязательный объект EntityKey, LockMode [] lockModes, гидратированные объекты IList, сеанс ISessionImplementor)
в NHibernate.Loader.Loader.GetRowFromResultSet (IDataReader resultSet, сеанс ISessionImplementor, QueryParameters queryParameters, LockMode [] lockModeArray, EntityKey необязательныйObjectKey, ключи IList hydratedObjects, EntityKey [*] * 1022, логический возврат) в NHibernate.Loader.Loader.DoQuery (сеанс ISessionImplementor, QueryParameters queryParameters, логическое returnProxies)
в NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections (сеанс ISessionImplementor, QueryParameters queryParameters, логическое returnProxies)
...
в NHibernate.Linq.CriteriaResultReader 1.<GetEnumerator>d__0.MoveNext()<br> at System.Collections.Generic.List 1..ctor (IEnumerable 1 collection)<br> at System.Linq.Enumerable.ToList[TSource](IEnumerable 1 source)
...

Я переименовал свои классы и вынул несущественные свойства и тому подобное, чтобы упростить, но уровни наследования точно такие же, как в моем реальном сценарии.

Занятия:

public abstract class BaseClass : 
{
    public Guid ID { get; set; }
    ...

}
public abstract class ClassA : BaseClass
{
    public ClassB RelatedObject { get; set; }
}
public abstract class ClassB : BaseClass
{
    public ClassA RelatedObject { get; set; }
}
public abstract class ClassC : BaseClass
{
    ...
}

public class ClassA1 : ClassA
{
    ...
}
public class ClassA2 : ClassA
{
    ...
}

public class ClassB1 : ClassB
{
    ...
}
public class ClassB2 : ClassB
{
    ...
}

public class ClassC1 : ClassC
{
    ...
}
public class ClassC2 : ClassC
{
    ...
}

Существует таблица для базового класса, а затем отдельные таблицы для некоторых конкретных классов, но не для всех. Соответствующий столбец для связанного объекта находится в главной таблице.

BaseClassTable:
-------------------------------
| ID | Kind | RelatedObjectID |
-------------------------------

Individual tables:
---------------------------------
| ID | some specific properties |
---------------------------------

Отображение:

<class name="MyNamespace.BaseClass, MyNamespace" table="BaseClassTable" discriminator-value="BC" abstract="true">
    <id name="ID" type="System.Guid" column="ID" unsaved-value="00000000-0000-0000-0000-000000000000">
      <generator class="guid" />
    </id>
    <discriminator column="Kind" type="System.String"/>
    ...
    <subclass name="MyNamespace.ClassA, MyNamespace" discriminator-value="A" abstract="true">
        <many-to-one name="RelatedObject" class="MyNamespace.ClassB, MyNamespace" column="RelatedObjectID"/>
    </subclass>
    <subclass name="MyNamespace.ClassB, MyNamespace" discriminator-value="B" abstract="true">
        <many-to-one name="RelatedObject" class="MyNamespace.ClassA, MyNamespace" column="RelatedObjectID"/>
    </subclass>
    <subclass name="MyNamespace.ClassC, MyNamespace" discriminator-value="C" abstract="true">
    ...
    </subclass>
  </class>
  <subclass name="MyNamespace.ClassA1, MyNamespace" extends="MyNamespace.ClassA, MyNamespace" discriminator-value="A1">
    <join table="ClassA1Table">
        <key column="ID"/>
        ...
    </join> 
    ...
  </subclass>
  <subclass name="MyNamespace.ClassA2, MyNamespace" extends="MyNamespace.ClassA, MyNamespace" discriminator-value="A2">
    ...
  </subclass>
  <subclass name="MyNamespace.ClassB1, MyNamespace" extends="MyNamespace.ClassB, MyNamespace" discriminator-value="B1">
    ...
  </subclass>
  <subclass name="MyNamespace.ClassB2, MyNamespace" extends="MyNamespace.ClassB, MyNamespace" discriminator-value="B2">
    ...
  </subclass>
  <subclass name="MyNamespace.ClassC1, MyNamespace" extends="MyNamespace.ClassC, MyNamespace" discriminator-value="C1">
    ...
      </subclass>
  <subclass name="MyNamespace.ClassC2, MyNamespace" extends="MyNamespace.ClassC, MyNamespace" discriminator-value="C2">
    ...
  </subclass>

Конечно, в БД у меня будут только значения A1, A2, B1, B2, C1 и C2 для дискриминатора.

Кто-нибудь сталкивался с чем-то подобным раньше? Можно ли сопоставить свойство как базовый класс, а затем загрузить экземпляр конкретного класса для того же идентификатора? Есть ли лучший способ сделать это? Спасибо!

Это вызов, который выдает исключение:

Ошибка выдается при попытке извлечь объекты с помощью IQueryable из моего контекста данных:

List<MyNamespace.BaseClass> items = context.MyObjects.ToList();

И в моем контексте данных свойство IQueryable выглядит так:

IQueryable<MyNamespace.BaseClass> IMyDataContext.MyObjects
{
   get
   {
      return this.Session.Linq<MyNamespace.BaseClass>();
   }
}
...