2010-01-13 163 views
3

在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); 

(這是一個簡化版本,我們真的加載從配置我們的程序集名稱,但它是不相關的這個問題。)

回答

1

MSDN says that, for the Assembly Location property,

如果程序集是從字節數組加載的,例如使用Load(array [])方法重載時,返回的值是一個空字符串(「」)。

也就是說的,而不是從磁盤其文件位置加載組件,有人在字節數組讀入並加載起來的方式。谷歌管告訴我,這會導致程序集加載a different security context,因此,NHibernate將它視爲不同的類型並不奇怪。

您是否有可能以某種方式加載程序集的機制,可能是某種競爭條件?我會嘗試從這裏進入兔子洞。祝你好運!

+0

感謝您的回覆! 我們沒有從字節數組中加載程序集,我們正在按名稱加載程序集。加載信息已被添加到現在的問題。 – 2010-01-14 09:04:15

+0

嗯。你可以在Application_Start中驗證'Location'嗎?如果它在那裏,那麼我想知道代理生成是否發生了一些奇怪的事情...... – 2010-01-14 12:17:20

+1

我們錯了:我們確實使用Load(Byte []),它可能是一個競爭條件。 除了在初始化ActiveRecord時加載程序集外,我們還註冊了一個自定義的VirtualPathProvider。在這個提供程序的初始化中,我們從字節數組中加載了一些相同的程序集。 我不知道ASP.NET框架何時初始化提供程序,但它可能是ActiveRecord和VirtualPathProvider的初始化之間的競爭條件。裝配加載的一些清理修復了問題:-) – 2010-01-19 10:24:45

相關問題