ERROR: Loading object was of wrong class
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));
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.
精彩评论