NHibernate QueryException: несоответствие типов, ожидаемый тип == фактический тип - PullRequest
3 голосов
/ 14 января 2010

У нас действительно странная проблема в веб-приложении при использовании ActiveRecord 2.0 с NHibernate 2.1.0 (также пробовал 2.1.2). Извините, если это описание немного расплывчато, но у нас возникают проблемы с пониманием того, что происходит. Мы работаем над крупным корпоративным приложением, где пытаемся изолировать проблему и привести небольшой пример, но мы еще не достигли этого.

Проблема возникает, когда мы пытаемся выполнить специальный запрос для двух объектов с отношением многие-к-одному. Это код, который вызовет проблему:

int testItemId = 1;
TestItem testItem = ActiveRecordMediator<TestItem>.FindByPrimaryKey(testItemId, false);
DetachedCriteria testCriteria = DetachedCriteria.For<TestItemRevision>();
testCriteria.Add(Expression.Eq("TestItem", testItem));
TestItemRevision testRevision = ActiveRecordMediator<TestItemRevision>.FindFirst(testCriteria);

При выполнении FindFirst (или FindAll) выдается следующее исключение: Несоответствие типов в NHibernate.Criterion.SimpleExpression: TestItem ожидаемый тип MyProduct.Core.DomainModel.Test.TestItem, фактический тип MyProduct.Core.DomainModel.Test.TestItem

Как видите, ожидаемый тип == фактический тип.

Мы обнаружили, что это исключение выдается в NHibernate.Criterion.CriterionUtil.GetColumnNamesUsingPropertyName (...). Мы собрали нашу собственную версию NHibernate, с некоторыми дополнительными входами здесь. Когда все в порядке, мы получаем это:

propertyType.ReturnedClass.Assembly: MyProduct.Core.DomainModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
propertyType.ReturnedClass.Assembly.Location: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\root\daa38103\4727b73f\assembly\dl3\bb8c85b9\7202540f_a593ca01\MyProduct.Core.DomainModel.DLL
value.GetType().Assembly: MyProduct.Core.DomainModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
value.GetType().Assembly.Location: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\root\daa38103\4727b73f\assembly\dl3\bb8c85b9\7202540f_a593ca01\MyProduct.Core.DomainModel.DLL

Когда выдается исключение, мы получаем это:

propertyType.ReturnedClass.Assembly: MyProduct.Core.DomainModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
propertyType.ReturnedClass.Assembly.Location == String.Empty: True
value.GetType().Assembly: MyProduct.Core.DomainModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
value.GetType().Assembly.Location: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\root\daa38103\4727b73f\assembly\dl3\bb8c85b9\7202540f_a593ca01\MyProduct.Core.DomainModel.DLL

Т.е. при возникновении исключения ожидаемый тип не имеет местоположения и рассматривается как другая сборка.

Действительно странная вещь заключается в следующем: исключение не всегда выбрасывается. Мы должны перезапустить пул приложений в IIS, чтобы воспроизвести проблему, и только приблизительно 1 из 3 перезапусков фактически вызовет ее. Мы думаем, что этот запрос должен быть первым, что происходит после перезапуска, но мы не уверены в этом. После того, как исключение было сгенерировано один раз, запрос не будет работать снова, пока пул приложений не будет перезапущен или библиотека DLL в папке bin не будет обновлена. Перезапуск веб-сайта или изменение файла Web.config не помогает. Мы воспроизвели проблему на WinServer 2003 / IIS6 и Win7 / IIS7.5.

Мы пытались настроить тестовый проект с точно такими же сопоставлениями объектов и точно таким же запросом, но мы пока не смогли воспроизвести проблему за пределами большого приложения. Кто-нибудь знает, что может вызвать что-то подобное?

Edit:

Вот как мы загружаем нашу сборку в global.asax Application_Start:

Assembly[] assemblies = new[] { Assembly.Load("MyProduct.Core.DomainModel") };
ActiveRecordStarter.Initialize(assemblies, ActiveRecordSectionHandler.Instance);

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

1 Ответ

1 голос
/ 14 января 2010

MSDN говорит, что для свойства Assembly Location,

Если сборка загружается из байтового массива, например при использовании перегрузки метода Load (array []), возвращаемое значение представляет собой пустую строку ("").

То есть, вместо загрузки сборки из ее расположения на диске, кто-то прочитал массив байтов и таким образом загрузил его. Гугл-тубусы говорят мне, что это приведет к загрузке сборки с другим контекстом безопасности , и поэтому неудивительно, что NHibernate увидит его как другие типы.

Возможно ли, что у вас есть какой-то механизм, который может загружать сборку таким образом, возможно, в каком-то состоянии гонки? Я бы попробовал войти в кроличью нору отсюда. Удачи!

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