我有旧的旧数据库,它们的表中有死链接。我有像这样在nhibernate中映射的类:
<class name="Visible" table="table_visible">
<composite-id>
<key-many-to-one column="object_id" name="ObjectA" />
<key-many-to-one column="sub_object_id" name="SubObject" />
</composite-id>
<property column="visible" name="VisibleRow" />
</class>
和
public class Visible
{
public virtual ObjectAClass ObjectA { get; set; }
public virtual SubObjectClass SubObject { get; set; }
public virtual bool VisibleRow { get; set; }
public override bool Equals(object obj)
{
var other = ((Visible)obj);
return this.ObjectA.Equals(other.ObjectA) && this.SubObject.Equals(other.SubObject);
}
public override int GetHashCode()
{
return this.ObjectA.GetHashCode() + (this.SubObject != null? this.SubObject.GetHashCode(): 0);
}
}
现在一切正常,当数据库中的所有连接都正确时,但是当我发现这样的sub_object_id没有实体时,nhibernate会抛出错误
No row with the given identifier exists:[SubObject#123]
有没有办法映射复合键,这样当找不到它的子实体时,整个实体就不会被加载(比如内连接)?
NHibernate v2.0.50727
答案 0 :(得分:1)
遵循Daniel Schilling关于使用where where子查询获取可见实体的想法,发现映射中有loader
个元素。
<class name="ObjectA" table="table_object">
.........
<set name="VisibleList" cascade="all" lazy="false" inverse="true">
<key column="object_id" />
<one-to-many class="Visible" />
<loader query-ref="valid_entities"/>
</set>
</class>
<sql-query name="valid_entities">
<load-collection alias="v" role="ObjectA.VisibleList"/>
SELECT {v.*}
FROM table_visible v
INNER JOIN table_sub_entities e ON e.sub_entity_id=v.sub_entity_id
WHERE v.object_id=?
</sql-query>
没有其他事情需要改变。
答案 1 :(得分:0)
<key-many-to-one column="sub_object_id" name="SubObject" not-found="ignore" />
......可能会有所帮助。来自NHibernate Documentation ...
ignore
会将缺失的行视为空关联
请注意与使用此选项相关的性能损失。每当NHibernate获取Visible
实体时,它也必须获取SubObject
。如果你不继续在你的查询中获取它,这意味着NHibernate将发出大量的延迟加载。
这不符合您的“当找不到其子实体时,整个实体将无法加载”目标。相反,NHibernate将为您提供一个具有空子实体的实体。如果您想要类似内部联接的行为,那么我认为您需要使用Visible
子查询来获取where exists
个实体,以确保SubObject
实际存在。
最佳选项是修复数据库中的数据并添加外键约束。
我刚刚遇到过这个问题:Relations with not-found="ignore"。我保证我不会复制利玛窦的内容 - 我是根据自己的经验写的。