当我尝试加载一个将子实体映射为包的实体,并且子实体和父实体之间的键是一个字符串时,如果该键的大小写与父类不匹配,则不会填充生成的包。身份证。
如果 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 :(得分:0)
使用事件监听器尝试解决问题几天后,调试结果发现NHibernate存在一个错误。
我能够通过更改实际的NHibernate源,重建和重新链接来解决问题。 我使用的技术使实际的实体键保持不变,因此保留了它来自或进入数据库时的情况。
当NHibernate加载实体时,会创建&#34;键&#34; ,它基本上只是一个标记,它在IDictionary中存储和测试&lt;&gt; ;表示会话或实体及其相关依赖集合的缓存。这个&#34; key&#34; 不够聪明,不能进行不区分大小写的比较。为了做到这一点,我必须修改哈希码并调整Equals()以进行不区分大小写的比较,这样如果密钥中的大小写与测试值不同,它总是会被命中。
如果你习惯于建立NHibernate并拥有技术债务,直到它被修复,这是我的补丁:
修改EntityKey.cs,CollectionKey.cs和CacheKey.cs
我通过简单地使用大写进行比较来欺骗,而不是做不区分大小写的比较。
示例代码:
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。