2010-07-28 55 views
1

我有一個MVC/Nhibernate應用程序給我下面。錯誤:加載對象是錯誤的類

[WrongClassException: Object with id: f7eab616-76b2-4602-8643-b4466e91a33f was not of the specified subclass: AgileThought.ERP.Domain.CRM.Client (loading object was of wrong class [AgileThought.ERP.Domain.HR.SalesRepresentative])] NHibernate.Loader.Loader.InstanceAlreadyLoaded(IDataReader rs, Int32 i, IEntityPersister persister, EntityKey key, Object obj, LockMode lockMode, ISessionImplementor session) +229

我從堆棧跟蹤相信該行NHibernate.Loader.Loader.InstanceAlreadyLoaded說,對象已經加載。

問題是該對象可能是幾個具有相同GUID的類型。 IE

客戶端從一個人

一個員工從一個人

一個銷售代表,繼承員工

繼承了我的開發環境繼承,我的用戶帳戶的所有三個實體類型。

現在的問題是,現在當我在客戶端上進行搜索時,它會看到銷售代表的GUID並假定我想要銷售代表對象。 我的代碼的下一行失敗,因爲它預計客戶端列表,但一個對象是銷售代表

我在搜索中看到了幾個類似的問題,但他們似乎都圍繞使用鑑別器。我爲這些子類中的每一個都有一個單獨的表,只是列出了GUID和任何額外的屬性。 我也看到用hibernate(java)報告的這個錯誤作爲代碼錯誤,但文章稱它在Nhibernate Port中糾正了這個問題的一個斷開的鏈接。

Nhibernate API查詢指定了它應該得到的對象類型,所以我不確定我還能做什麼。 有沒有辦法強制一個新的查詢?

這種情況在現實生活中不太可能發生,但我擔心在目前的情況下,我的登錄不能成爲客戶和銷售代表,我毫不懷疑這會在應用程序的其他地方引發更大的問題一些其他人的類型將被使用。 (每種類型有幾個獨立的屬性,我不想使用disctiminator或用戶角色來指定那裏的人類型。)

任何意見,將不勝感激。

請在下面找到下面的代碼。

搜索方法:

public IEnumerable<Client> NewContacts(Guid userGUID) 
    { 
     SalesRepresentative rep = new SalesRepresentativeRepository().GetById(userGUID); 
     List<Client> result = new List<Client>(); 
     using (ISession session = NHibernateHelper.OpenSession()) 
     { 
      foreach (var i in rep.Projects) 
      { 
       ICriteria criteriaPerson = session.CreateCriteria(typeof(Client)); 
       criteriaPerson.CreateAlias("ProjectsOfInterest","p"); 
       criteriaPerson.Add(Expression.Eq("p.EntityGUID", i.EntityGUID)); 
       //Distinct 
       criteriaPerson.SetResultTransformer(new NHibernate.Transform.DistinctRootEntityResultTransformer()); 

       result.AddRange(criteriaPerson.List<Client>()); 
      } 
      return result.Distinct(); 
     } 
    } 

的對象加載已經加載的銷售代表就行了:

SalesRepresentative rep = new SalesRepresentativeRepository().GetById(userGUID); 

的問題是上線:

result.AddRange(criteriaPerson.List<Client>()); 

因爲我的一位客戶是我,銷售代表

最初這段代碼沒有圍繞項目循環,而是通過別名的內部連接。 這只是一個試圖通過從查詢中找出答案的嘗試,但它具有相同的結果。

    ICriteria criteriaPerson = session.CreateCriteria(typeof(Client)); 
       criteriaPerson.CreateAlias("ProjectsOfInterest", "p"); 
       criteriaPerson.CreateAlias("ProjectsOfInterest.SalesRepresentatives", "rep"); 
       criteriaPerson.Add(Expression.Eq("rep.EntityGUID", userGUID)); 

回答

1

我在這個同樣的錯誤今日下跌(第二次實際上),我終於明白什麼是這裏的問題。

我不知道其他ORM,但使用nHibernate,你不能在兩個不同的類(子類)上共享一個Id。這不是繼承應該在nHibernate中的方式。 Table-per-class層次結構是爲了使用不同的表來指定一個父表(在你的問題中,你正在嘗試相反的方式)。

所有這些實際上是有道理的,因爲訪問客戶端或員工您實際上是指人員ID(起初我沒有注意到這一點,但現在是完全清楚)。

解決方案是重構域模型,並將類之間的關係從「is-a」更改爲「has-a」關係,並通過接口公開屬性(如果需要)。