У нас действительно странная проблема в веб-приложении при использовании 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);
(Это упрощенная версия, мы действительно загружаем имена наших сборок из конфигурации, но это не относится к этой проблеме.)