ОШИБКА: загрузка объекта была неправильного класса - PullRequest
1 голос
/ 28 июля 2010

У меня есть приложение MVC / Nhibernate, которое дает мне следующее.

[WrongClassException: объект с идентификатором: f7eab616-76b2-4602-8643-b4466e91a33f не относится к указанному подклассу: AgileThought.ERP.Domain.CRM.Client (загружаемый объект был неправильного класса [AgileThought.ERP.Domain.HR .Торговый представитель])] NHibernate.Loader.Loader.InstanceAlreadyLoaded (персистент IDataReader, Int32 i, IEntityPersister, ключ EntityKey, объектный объект, LockMode lockMode, сеанс ISessionImplementor) + 229

По трассировке стека я считаю, что строка NHibernate.Loader.Loader.InstanceAlreadyLoaded говорит, что объект уже загружен.

Проблема в том, что объект может быть нескольких типов с одинаковым GUID. IE

Клиент наследуется от человека

Сотрудник наследуется от человека

торговый представитель унаследовал от сотрудника

В моей среде разработчиков моя учетная запись пользователя имеет все три типа сущностей.

Проблема в том, что теперь, когда я выполняю поиск на клиенте, он видит GUID из торгового представителя и предполагает, что мне нужен мой объект торгового представителя. Следующая строка моего кода терпит неудачу, так как она ожидает список клиентов, но один объект - торговый представитель.

Я видел несколько похожих проблем при поиске, но все они вращаются вокруг использования дискриминатора. У меня есть отдельная таблица для каждого из этих подклассов, просто перечисляя GUID и любые дополнительные свойства. Я также видел эту ошибку, о которой сообщалось в hibernate (java), как об ошибке кода, но в статье говорилось, что она была исправлена ​​в Nhibernate Port с неработающей ссылкой на проблему.

Запрос API Nhibernate указывает тип моего объекта, который он должен получать, поэтому я не уверен, что еще я могу сделать. Есть ли способ заставить новый запрос?

Ситуация вряд ли произойдет в реальной жизни, но я обеспокоен тем, что мой логин не может быть и клиентом, и торговым представителем в текущей ситуации, я не сомневаюсь, что это вызовет еще большую проблему в приложении, где некоторые другие типы людей будут использоваться. (У каждого типа есть несколько отдельных свойств, я не хочу использовать дисктиминатор или пользовательские роли для указания типа человека.)

Любой совет будет высоко ценится.

Пожалуйста, найдите код ниже.

Метод поиска:

 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 Ответ

1 голос
/ 10 января 2011

Я попал в эту же ошибку сегодня (во второй раз на самом деле), и я наконец понял, в чем здесь проблема.

Я не знаю, сколько других ORM, но, используя nHibernate, вы не можете использовать один и тот же идентификатор для двух разных классов (подклассов). Это не тот способ наследования, который должен быть в nHibernate. Предполагается, что иерархия таблиц для классов должна иметь отдельные таблицы для указания родительской таблицы (в своей проблеме вы пытаетесь использовать противоположное).

Все это на самом деле имеет смысл, поскольку для доступа к Клиенту или Сотруднику вы на самом деле ссылаетесь на Идентификатор личности (сначала я не обращал на это внимания, но теперь все понятно).

Решение состоит в том, чтобы реорганизовать модель предметной области и изменить отношение между вашими классами с отношения "is-a" на отношение "has-a" и предоставить общие свойства (при необходимости) через интерфейс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...