错误:加载对象属于错误的类

发布于 2024-09-12 12:21:41 字数 2717 浏览 5 评论 0原文

我有一个 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会话)+229

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

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

客户从人员继承

员工从人员继承 销售

代表从员工继承

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

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

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

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

这种情况在现实生活中不太可能发生,但我担心在当前情况下我的登录名不能同时是客户和销售代表,我毫不怀疑这会在其他人键入的应用程序中的其他地方引起更大的问题将被使用。 (每种类型都有一些单独的属性,我不想使用鉴别器或用户角色来指定人员类型。)

任何建议将不胜感激。

请在下面找到代码。

搜索方法:

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

I have an MVC/Nhibernate app that is giving me the below.

[WrongClassException: Object with id: f7eab616-76b2-4602-8643-b4466e91a33f was not of the specified subclass: AgileThought.ERP.Domain.CRM.Client (loading object was of wrong class [AgileThought.ERP.Domain.HR.SalesRepresentative])]
NHibernate.Loader.Loader.InstanceAlreadyLoaded(IDataReader rs, Int32 i, IEntityPersister persister, EntityKey key, Object obj, LockMode lockMode, ISessionImplementor session) +229

I believe from the stack trace that the line NHibernate.Loader.Loader.InstanceAlreadyLoaded says the object is already loaded.

The problem is that the object may be of a few types which have the same GUID.
IE

a Client Inherits from a Person

a Employee Inherits from a Person

a Sales Rep Inherits from Employee

In my dev environment, my user account has all three entity types.

The problem is that now when I do a search on a Client, it sees the GUID from a Sales Rep and assumes that I want my Sales Rep object.
The next line of my code fails as it is expecting a Client list, but one object is a Sales Rep.

I have seen several similar issue in searching but they all seem to revolve around using a discriminator. I have a seperate table for each of these sub classes, just listing the GUID and any extra properties.
I have also seen this error reported with hibernate (java) as a code error, but the article said it was corrected in Nhibernate Port wtih a broken link to the issue.

The Nhibernate API query specifies my object type it should be getting, so I am not sure what else I can do.
Is there a way to force a fresh query?

The situation is unlikely to occur in real life, but I am concerned that I my login cant be both a client and a sales rep under the current situation, I have no doubt this will cause greater issue elswhere in the application where some other person types will be used.
(Each type has a few seperate properties, I dont want to use a disctiminator or user Roles to specifiy there person type.)

Any advise would be much appreciated.

Please find code below.

Search Method:

 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();
         }
    }

The object is loaded already loaded as a Sales Rep on the line:

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

The issue is on the line:

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

because one of my clients is me, the Sales Rep.

Originally this code didn't have a loop around the project, but an inner join via alias's.
This was just one attempt to find an answer by taking it out of the query, but it had the same result.

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

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

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦里泪两行 2024-09-19 12:21:41

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

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

所有这些实际上都是有意义的,因为要访问客户或员工,您实际上引用的是人员 ID(起初我没有注意到这一点,但现在完全清楚了)。

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

I fell in this same error today (for the second time actually) and I finally realized what's the issue here.

I don't knwo abount others ORM but using nHibernate you can't share an Id over two different classes (subclasses). That's not the way inheritance is supposed to be in nHibernate. Table-per-class hierarchy is meant to have separate tables to specify a parent table (in your issue you are trying the opposite).

All this actually make sense since to access Client or Employee you actually refer to the Person Id (at first I didn't paid attention to this but now is totally clear).

The solution is to refactor the domain model and change the relationship between you classes from as "is-a" to a "has-a" relationship and expose common properties (if needed) via an interface.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文