错误:加载对象的类错误

时间:2010-07-28 16:56:29

标签: .net nhibernate model-view-controller

我有一个MVC / Nhibernate应用程序给我下面的内容。

  

[WrongClassException:id为f7eab616-76b2-4602-8643-b4466e91a33f的对象不属于指定的子类:AgileThought.ERP.Domain.CRM.Client(加载对象的类错误[AgileThought.ERP.Domain.HR] 。销售代表])]      NHibernate.Loader.Loader.InstanceAlreadyLoaded(IDataReader rs,Int32 i,IEntityPersister persister,EntityKey key,Object obj,LockMode lockMode,ISessionImplementor session)+229

我相信在堆栈跟踪中, NHibernate.Loader.Loader.InstanceAlreadyLoaded 行表示该对象已经加载。

问题是该对象可能是具有相同GUID的几种类型。 IE

客户端从人员继承

员工从人员继承

销售代表从员工继承

在我的开发环境中,我的用户帐户拥有所有三种实体类型。

现在的问题是,当我在客户端上进行搜索时,它会看到来自销售代表的GUID并假设我需要我的销售代表对象。 我的代码的下一行失败,因为它期望一个客户列表,但一个对象是销售代表。

我在搜索中看到了几个类似的问题,但它们似乎都围绕着使用鉴别器。我为每个子类都有一个单独的表,只列出GUID和任何额外的属性。 我也看到用hibernate(java)报告的这个错误是一个代码错误,但文章说它在Nhibernate Port中已经纠正了这个问题的链接。

Nhibernate API查询指定了它应该获取的对象类型,所以我不确定我还能做什么。 有没有办法强制进行新的查询?

在现实生活中不太可能出现这种情况,但我担心在目前的情况下我的登录不能同时是客户和销售代表,我毫不怀疑这会在应用程序中导致更大的问题将使用其他人类型。 (每种类型都有一些单独的属性,我不想使用disctiminator或用户角色来指定那里的人类型。)

任何建议都会非常感激。

请在下面找到代码。

搜索方法:

 public IEnumerable<Client> NewContacts(Guid userGUID)
    { 
         SalesRepresentative rep = new SalesRepresentativeRepository().GetById(userGUID);
         List<Client> result = new List<Client>();
         using (ISession session = NHibernateHelper.OpenSession())
         {
             foreach (var i in rep.Projects)
             {
                 ICriteria criteriaPerson = session.CreateCriteria(typeof(Client));
                 criteriaPerson.CreateAlias("ProjectsOfInterest","p");
                 criteriaPerson.Add(Expression.Eq("p.EntityGUID", i.EntityGUID));
                 //Distinct
                 criteriaPerson.SetResultTransformer(new NHibernate.Transform.DistinctRootEntityResultTransformer());

                 result.AddRange(criteriaPerson.List<Client>());
             }
             return result.Distinct();
         }
    }

该对象已作为销售代表加载到该行:

SalesRepresentative rep = new SalesRepresentativeRepository().GetById(userGUID);

问题在于:

result.AddRange(criteriaPerson.List<Client>());

因为我的一位客户是我,销售代表。

最初这段代码没有围绕项目循环,而是通过别名的内部联接。 这只是一次尝试通过将其从查询中删除来找到答案,但结果相同。

                 ICriteria criteriaPerson = session.CreateCriteria(typeof(Client));
                 criteriaPerson.CreateAlias("ProjectsOfInterest", "p");
                 criteriaPerson.CreateAlias("ProjectsOfInterest.SalesRepresentatives", "rep");
                 criteriaPerson.Add(Expression.Eq("rep.EntityGUID", userGUID));

1 个答案:

答案 0 :(得分:1)

今天我遇到了同样的错误(实际上是第二次),我终于意识到这里的问题是什么。

我不知道其他ORM但是使用nHibernate你不能在两个不同的类(子类)上共享一个Id。这不是继承应该在nHibernate中的方式。每个类的表层次结构意味着有单独的表来指定父表(在您的问题中,您尝试相反)。

所有这一切实际上都有意义,因为访问客户或员工你实际上是指人员ID(起初我没有注意到这一点,但现在已经完全清楚了)。

解决方案是重构域模型并将类之间的关系从“is-a”更改为“has-a”关系,并通过接口公开公共属性(如果需要)。