2010-01-13 3 views
3

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

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

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

MSDN says that, for the Assembly Location property,

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

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

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

+0

Спасибо за ответ! Мы не загружаем сборку из массива байтов, мы загружаем ее по имени. К этому вопросу добавлена ​​информация о загрузке. –

+0

Хм. Вы можете проверить «Местоположение» в Application_Start? Если это правильно, то я задаюсь вопросом, происходит ли что-то странное с генерацией прокси ... –

+1

Мы ошибались: мы использовали Load (Byte []), и это, вероятно, было гоночным. В дополнение к загрузке сборок при инициализации ActiveRecord мы также регистрировали пользовательский VirtualPathProvider. При инициализации этого провайдера мы загружали некоторые из тех же сборок из массива байтов. Я не знаю точно, когда инфраструктура ASP.NET инициализирует провайдера, но это, вероятно, было условием гонки между инициализацией ActiveRecord и VirtualPathProvider. Небольшая очистка сборки загрузила проблему :-) –

Смежные вопросы