在NHibernate 2.1.0中使用ActiveRecord 2.0(也试过2.1.2)时,Web应用程序中存在这个奇怪的问题。如果这个描述有点模糊,我很抱歉,但是我们在理解到底发生了什么时遇到问题。我们正在研究一个大型企业应用程序,我们正在试图隔离这个问题并做一个小例子,但我们还没有完成。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版本,在这里有一些额外的日志记录。 当一切OK,我们得到这样的:
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中回收应用程序池以重现此问题,并且只有三分之一的重新启动会实际触发它。我们认为这个查询必须是重启后发生的第一件事,但我们不确定这一点。在异常被抛出一次之后,查询将不会再次工作,直到应用程序池已被回收,或bin文件夹中的DLL已被更新。重新启动Web站点或更改Web.config不起作用。我们在WinServer 2003/IIS6和Win7/IIS7.5上都重现了这个问题。
我们试图设置一个完全相同的对象映射和完全相同的查询的测试项目,但是我们还没有能够在大型应用程序之外重现问题。有没有人有任何线索可能会导致这样的事情?
编辑:
这是我们如何加载我们的装配,在Global.asax中的Application_Start:
Assembly[] assemblies = new[] { Assembly.Load("MyProduct.Core.DomainModel") };
ActiveRecordStarter.Initialize(assemblies, ActiveRecordSectionHandler.Instance);
(这是一个简化版本,我们真的加载从配置我们的程序集名称,但它是不相关的这个问题。)
感谢您的回复! 我们没有从字节数组中加载程序集,我们正在按名称加载程序集。加载信息已被添加到现在的问题。 – 2010-01-14 09:04:15
嗯。你可以在Application_Start中验证'Location'吗?如果它在那里,那么我想知道代理生成是否发生了一些奇怪的事情...... – 2010-01-14 12:17:20
我们错了:我们确实使用Load(Byte []),它可能是一个竞争条件。 除了在初始化ActiveRecord时加载程序集外,我们还注册了一个自定义的VirtualPathProvider。在这个提供程序的初始化中,我们从字节数组中加载了一些相同的程序集。 我不知道ASP.NET框架何时初始化提供程序,但它可能是ActiveRecord和VirtualPathProvider的初始化之间的竞争条件。装配加载的一些清理修复了问题:-) – 2010-01-19 10:24:45