0

當我嘗試加載一個實體,該實體具有映射爲包的子實體,並且子實體和父級之間的鍵是字符串時,生成的包將不會如果密鑰的大小寫與父母的ID屬性不匹配,則填充。如何使用不區分大小寫的鍵映射NHibernate包

如果Office.ID == 「MyOfficePromotionalContent.ContextKey == 「myoffice,收集不加載促銷,即使NHProfiler表明,它是由返回數據庫

如果Office.ID == 「MyOffice」 和* PromotionalContent.ContextKey == 「MyOffice」,收集執行負載

<class name="Office" table="Office" lazy="true"> 
     <id name="ID" column="OfficeNum"> 
      <generator class="assigned" /> 
     </id> 
     <property name="Name" column="OfficeName" /> 
     <property name="PhoneNumber" column="PhoneNum" /> 
     <bag name="Promotions" lazy="true" where="ContextType='Office'" > 
     <key column="ContextKey"/> 
     <one-to-many class="PromotionalContent"/> 
     </bag>... 

這是NHibernate版本4.0.3。

我該如何映射它,或者修復它,以便它始終加載而不管大小寫嗎?

+0

什麼是底層數據庫? – Fran

+0

MSSQL 2014.我使用NHProfiler我能夠證明SQL Server正在返回兩種情況下的數據,所以它似乎是會話或緩存的問題。 – neoscribe

回答

0

經過幾天嘗試解決使用事件偵聽器的問題,調試後發現NHibernate中存在一個錯誤。

我能夠通過改變實際的NHibernate源代碼,重建和重新鏈接來解決問題。 我使用的技術使實際的實體鍵保持原樣,因此保留大小寫的情況,因爲它來自或進入數據庫。

當NHibernate的加載一個實體,「鑰匙」被創建基本上是一個標記存儲和測試一個IDictionary <>表示會話或實體的高速緩存及其相關,依賴集合。這「關鍵」是不夠智能做不區分大小寫的比較。爲了做到這一點,我必須修改哈希碼並調整Equals()以進行不區分大小寫的比較,以便在密鑰內的情況與測試值不同的情況下始終得到匹配。

如果您熟悉建築NHibernate和擁有高科技的債務,直到它是固定的,這裏是我的補丁:

修改EntityKey.cs,CollectionKey.cs和CacheKey.cs

  1. GetHashCode() - 無論密鑰的情況如何,都需要返回一致的哈希碼。否則,Equals()會在案件不同時調用而不會調用
  2. 等於() - 需要返回true而不管大小寫。否則,您的實體和/或其子集合將被錯過。

我通過簡單地使用大寫字母進行比較而不是進行不區分大小寫的比較來欺騙我。

示例代碼:

EntityKey.cs

public override bool Equals(object other) 
    { 
     var otherKey = other as EntityKey; 
     if(otherKey==null) return false; 

     if (Identifier is string && otherKey.Identifier is string) 
     { 
      object thiskeySanitized = ((string)Identifier).ToUpper(); 
      object thatkeySanitized = ((string)otherKey.Identifier).ToUpper(); 
      return otherKey.rootEntityName.Equals(rootEntityName) && identifierType.IsEqual(thatkeySanitized, thiskeySanitized, entityMode, factory); 
     } 
     return 
      otherKey.rootEntityName.Equals(rootEntityName) 
      && identifierType.IsEqual(otherKey.Identifier, Identifier, entityMode, factory); 
    } 

    private int GenerateHashCode() 
    { 
     int result = 17; 
     object sanitizedIdentifier = (identifier is string) ? ((string) identifier).ToUpper() : identifier; 
     unchecked 
     { 
      result = 37 * result + rootEntityName.GetHashCode(); 
      result = 37 * result + identifierType.GetHashCode(sanitizedIdentifier, entityMode, factory); 
     } 
     return result; 
    } 

CollectionKey.cs

public override bool Equals(object obj) 
    { 
     CollectionKey that = (CollectionKey)obj; 
     if (this.key is string && that.key is string) 
     { 
      object thiskeySanitized = ((string)this.key).ToUpper(); 
      object thatkeySanitized = ((string)that.key).ToUpper(); 
      return that.role.Equals(role) && keyType.IsEqual(thatkeySanitized, thiskeySanitized, entityMode, factory); 
     } 
     return that.role.Equals(role) && keyType.IsEqual(that.key, key, entityMode, factory); 
    } 

    private int GenerateHashCode() 
    { 
     int result = 17; 
     unchecked 
     { 
      result = 37 * result + role.GetHashCode(); 
      object sanitizedIdentifier = (key is string) ? ((string)key).ToUpper() : key; 
      result = 37 * result + keyType.GetHashCode(sanitizedIdentifier, entityMode, factory); 
     } 
     return result; 
    } 

CacheKey.cs

public CacheKey(object id, IType type, string entityOrRoleName, EntityMode entityMode, ISessionFactoryImplementor factory) 
    { 
     key = id; 
     this.type = type; 
     this.entityOrRoleName = entityOrRoleName; 
     this.entityMode = entityMode; 
     object sanitizedIdentifier = (key is string) ? ((string)key).ToUpper() : key; 
     hashCode = type.GetHashCode(sanitizedIdentifier, entityMode, factory); 
    } 

    public override bool Equals(object obj) 
    { 
     CacheKey that = obj as CacheKey; 
     if (that == null) return false; 
     if (key is string && that.key is string) 
     { 
      object thiskeySanitized = ((string)key).ToUpper(); 
      object thatkeySanitized = ((string)that.key).ToUpper(); 
      return entityOrRoleName.Equals(that.entityOrRoleName) && type.IsEqual(thiskeySanitized, thatkeySanitized, entityMode); 
     } 
     return entityOrRoleName.Equals(that.entityOrRoleName) && type.IsEqual(key, that.key, entityMode); 
    } 

這個問題在2015年報告給NHibernate團隊 - https://nhibernate.jira.com/browse/NH-3833

+0

被丟棄爲不是一個錯誤。數據庫也可以區分大小寫。您可以通過將您的密鑰與自定義類型進行映射來實現自己的平等語義,如Alexander在[NH-3833](https://nhibernate.jira.com/browse/NH-3833)上所解釋的那樣。 –

+0

很酷,謝謝,我會看看如果工作和發佈結果。 http://nhibernate.info/blog/2009/10/15/mapping-different-types-iusertype.html – neoscribe