2012-08-22 30 views
1

我的實體看起來像這樣簡化: baseobject and product are abstract代理只發生繼承和隱式多態映射的類的持久性?

我使用xml文件映射。除了抽象類以外,每個類都有一個表和一個xml文件。由於我使用延遲加載,因此我有許多代理。奇怪的是,當我呼叫Refresh(obj)其中一個它每次都有效,除非對象是Product1Proxy或Product2Proxy類型。然後,我得到一個「沒有持續......代理」的錯誤。

我試過了什麼?

  • 添加<mapping assembly="Project.DomainModel"/>到的App.config
  • 檢查是否所有的.hbm.xml文件嵌入資源(他們)
  • 我的類是公共
  • 他們有一個公共的默認構造函數

我的NHibernate版本是3.3。

我最後的想法是我應該爲我的產品使用另一個映射,但爲什麼它會與CustomerProxy(和其他人)一起工作呢?在我看來,Customer和BaseObject與Product和Product1具有相同的關係。

難道是繼承映射嗎?我還沒有看到另一個問題嗎?

更新:現在我想呼籲他們Refresh(obj)之前Unproxy的對象,但該方法仍返回Product1Proxy例如。然後我試着myObject is INHibernateProxy但總是評估爲假。爲什麼NHibernate不能識別自己的代理?

UPDATE2:我只注意到myObject的,那就是類型Product1Proxy指出,其baseobject是產品而不是產品1。我完全錯了,還是應該這樣?

UPDATE3:

session.Refresh((NHibernate.Proxy.INHibernateProxy)product); 

例如,這導致無效的轉換異常(Product1Proxy不能被轉換爲INHibernateProxy)。

if (kitProduct is NHibernate.Proxy.INHibernateProxy) { 
... 
} 

永遠是真實的......

,如果我把這個

IList kitProductTemplates = ProductManager.Instance.LoadProductTemplates(checkBoxShowHidden.Checked); 

產品1(真正的產品1返回,無代理)的列表,但如果我遍歷該與foreach列表,對象是一個代理。查詢看起來是這樣的:

public IList LoadAllTemplates(bool showHidden) 
{ 
    IList loadedObjects = (IList)new ArrayList(); 
    try 
    { 
     ISession session = HibernateSessionManager.Instance.GetSession(); 
     ICriteria crit = session.CreateCriteria(typeof(Product1)); 
     crit.Add(Restrictions.Eq("IsTemplate", true)); 
     crit.SetResultTransformer(new DistinctRootEntityResultTransformer()); 
     crit.AddOrder(Order.Asc("Name")); 
     crit.SetFetchMode("PickingList", FetchMode.Join); 
     crit.SetFetchMode("SOP", FetchMode.Join); 

     if (!showHidden) { 

      crit.Add(Restrictions.Eq("IsHidden", false)); 
     } 
     loadedObjects = crit.List(); 
    } 
    catch (Exception ex) 
    { 
     throw (ex); 
    } 
    return loadedObjects; 
} 

(這個我剛剛發現,否則我會添加它更早)

UPDATE4:我可以再次縮小問題。當對象第一次加載時它不會發生。但我不能保證每一個可能的用例。

最好的問候,Expecto

回答

0

你應該有一個代理抽象類的映射。

代理是從可用於NH的信息生成的,而不需要觸摸DB(這是具有代理的整體感覺)。當您參考Product(可能是Product1Product2)時,則NH生成從ProductProductProxy)繼承的代理。要知道代理實際上應該是Product1還是Product2,它必須觸及DB,這不是我們想要的。

要解決該問題:通過使用子類或聯合子類映射Product和地圖Product1Product2。避免提及BaseObject,以避免BaseObjectProxy的產生。

編輯:如果您仍然需要引用BaseObject,請使用<any>

編輯2:請注意,您永遠不知道是否從查詢中獲取代理,除非您處於事務的開始階段。無論何時爲產品創建代理,NH都會從返回同一產品的每個查詢中繼續返回此代理。即使該查詢不會返回代理。這是爲了確保你總是得到相同的事物的同一個實例。

實施例:

在DB中,您有產品1 ID爲1,2,和3。

// NH creates a proxy. 
var proxy = session.Load<Product>(1); 

// NH returns all Product1 instances, including the proxy 
var allProducts = session.CreateCriteria(typeof(Product1)).List(); 

allProducts包含一個代理編號爲1和非專利代理編號爲2和3。

+0

我可以使用union-subclass嗎?我不想爲產品添加一張額外的表格,因爲它是抽象的。 –

+0

是的,union-subclass使用xml元素「subclass」進行映射。目前,您已經有兩個單獨的表格,兩個表格中都有通用的基類屬性。有第三個表可能是一個選項,因爲它更規範。 –

+0

我添加了關於使用任何引用BaseObject的註釋。 –