NHibernate:具有 id 的对象不属于指定的子类:(加载对象属于错误的类)

发布于 2024-09-13 13:02:37 字数 4802 浏览 0 评论 0原文

我收到以下错误:

ID 为 34dd93d3-374e-df11-9667-001aa03fa2c4 的对象不属于指定的子类:MyNamespace.ClassA(加载对象属于错误的类 [MyNamespace.ClassB1])

调用堆栈为:

at NHibernate.Loader.Loader.InstanceAlreadyLoaded(IDataReader rs, Int32 i, IEntityPersister persister, EntityKey key, Object obj, LockMode lockMode, ISessionImplementor session)
在NHibernate.Loader.Loader.GetRow(IDataReader rs,ILoadable []持久化,EntityKey []键,对象可选对象,EntityKey可选ObjectKey,LockMode [] lockModes,IList HydratedObjects,ISessionImplementor会话)
在NHibernate.Loader.Loader.GetRowFromResultSet(IDataReader resultSet,ISessionImplementor会话,QueryParameters queryParameters,LockMode [] lockModeArray,EntityKey可选ObjectKey,IList HydredObjects,EntityKey []键,布尔returnProxies)
在NHibernate.Loader.Loader.DoQuery(ISessionImplementor会话,QueryParameters queryParameters,布尔returnProxies)
在NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor会话,QueryParameters queryParameters,布尔returnProxies)
...
在 NHibernate.Linq.CriteriaResultReader1.d__0.MoveNext()
在 System.Collections.Generic.List
1..ctor(IEnumerable1 集合)
在 System.Linq.Enumerable.ToList[TSource](IEnumerable
1 源)
...

我已经重命名了我的类,并删除了不相关的属性等,以简化,但继承级别与我的真实场景完全相同。

类:

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 值。

以前有人遇到过这样的事情吗?是否可以将属性映射为基类,然后使用相同的 ID 加载具体类的实例?有更好的方法来实现这一点吗? 谢谢你!

这是引发异常的调用:

尝试使用 IQueryable 从我的数据上下文中检索对象时引发错误:

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

在我的数据上下文中,IQueryable 属性如下所示:

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

I am getting the error below:

Object with id: 34dd93d3-374e-df11-9667-001aa03fa2c4 was not of the specified subclass: MyNamespace.ClassA (loading object was of wrong class [MyNamespace.ClassB1])

Call stack is:

at NHibernate.Loader.Loader.InstanceAlreadyLoaded(IDataReader rs, Int32 i, IEntityPersister persister, EntityKey key, Object obj, LockMode lockMode, ISessionImplementor session)
at NHibernate.Loader.Loader.GetRow(IDataReader rs, ILoadable[] persisters, EntityKey[] keys, Object optionalObject, EntityKey optionalObjectKey, LockMode[] lockModes, IList hydratedObjects, ISessionImplementor session)
at NHibernate.Loader.Loader.GetRowFromResultSet(IDataReader resultSet, ISessionImplementor session, QueryParameters queryParameters, LockMode[] lockModeArray, EntityKey optionalObjectKey, IList hydratedObjects, EntityKey[] keys, Boolean returnProxies)
at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
...
at NHibernate.Linq.CriteriaResultReader1.<GetEnumerator>d__0.MoveNext()
at System.Collections.Generic.List
1..ctor(IEnumerable1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable
1 source)

I have renamed my classes and took out the irrelevant properties and such, to simplify, but the levels of inheritance are exactly like in my real scenario.

The classes:

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
{
    ...
}

There is a table for the base class, and then individual tables for some of the concrete classes, not all of them. The corresponding column for the related object is in the main table.

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

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

Mapping is:

<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>

Of course, in the DB I’m only going to have the A1, A2, B1, B2, C1 and C2 values for the discriminator.

Did anybody run into something like this before? Can a property be mapped as a base class and then have an instance of the concrete class loaded, for the same ID? Is there a better way to accomplish this?
Thank you!

This is the call that throws the exception:

The error is thrown when trying to retrieve objects using the IQueryable from my data context:

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

And in my data context, the IQueryable property looks like this:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文