0

하위 엔티티가 자루로 매핑 된 엔티티를로드하려고 시도하고 하위 엔티티와 부모 사이의 키가 문자열 인 경우 결과 가방은 키의 대문자가 부모의 ID 속성과 일치하지 않으면 채워집니다.NHibernate 가방을 대/소문자를 구분하지 않는 키로 매핑하는 방법

하면 Office.ID == "MyOffice"PromotionalContent.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()를 조정하여 대소 문자를 구분하지 않는 비교를 수행하여 키 내의 대/소문자가 테스트 값과 다른 경우 항상 히트가 발생하도록해야했습니다.

수정 EntityKey.cs, CollectionKey.cs 및 CacheKey.cs

  1. : 당신이 편안 건물 NHibernate에과가 고정 될 때까지 기술 빚을 소유하는 경우

    , 여기 내 패치입니다 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

,536,
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

관련 문제