C# 从集合中删除项目(NHibernate)
我有两个实体(父实体和子实体)之间的父子关系 我的父映射如下所示:C# 从集合中删除项目(NHibernate),c#,nhibernate,C#,Nhibernate,我有两个实体(父实体和子实体)之间的父子关系 我的父映射如下所示: <class name="Parent" table="Parents"> ... <bag name="Children" cascade="all"> <key column="ParentID"></key> <one-to-many class="Child"></one-to-many> &l
<class name="Parent" table="Parents">
...
<bag name="Children" cascade="all">
<key column="ParentID"></key>
<one-to-many class="Child"></one-to-many>
</bag>
</class>
子类引用了另一个父类Type。这种关系看起来像
注意:我为上面没有链接的url道歉,我似乎无法通过使用标记的url字符串中的星号
由于这种关系,当调用上述代码时,将生成一个更新查询,该查询将从子表中删除ParentID(设置为null)
从父.Children集合中删除时,是否可以强制NHibernate完全删除子记录
更新
@斯宾塞溶液
非常有吸引力的解决方案,因为这是可以在将来的类中实现的。但是,由于存储库模式中处理会话的方式(在我的特殊情况下),这几乎是不可能的,因为我们必须根据应用程序传递会话类型(CallSessionContext/WebSessionContext)
@杰米的解决方案
简单而快速的实现,但是我遇到了另一个障碍。我的子实体如下所示:
使用新方法时,NHibernate生成一个update语句,将TypeID和ParentID设置为null,而不是直接删除。如果我在实现过程中遗漏了一些东西,请告诉我,因为这种方法将毫无痛苦地向前推进
@,概述了取消对集合的引用以强制执行单个删除的想法。但是,与上述结果相同,将发出update语句
//Instantiate new collection and add persisted items
List<Child> children = new List<Child>();
children.AddRange(parent.Children);
//Find and remove requested items from new collection
var childrenToRemove = children
.Where(c => c.Type.TypeID == 1)
.ToList();
foreach (var c in childrenToRemove) { children.Remove(m); }
parent.Children = null;
//Set persisted collection to new list
parent.Children = Children;
//实例化新集合并添加持久化项
列表子项=新列表();
children.AddRange(parent.children);
//从新集合中查找并删除请求的项
var childrenToRemove=children
.其中(c=>c.Type.TypeID==1)
.ToList();
foreach(childrenToRemove中的var c){children.Remove(m);}
parent.Children=null;
//将持久化集合设置为新列表
父母。子女=子女;
解决方案
花了一点时间,但杰米的解决方案通过了一些额外的修改。对于未来的读者,基于以上我的课堂模型:
类型映射-反向=真,级联=全部
父映射-反向=真,级联=全部删除孤立
删除Jamie的解决方案中描述的方法。这确实会为每个孤立项生成一个delete语句,因此将来可以进行调优,但最终结果是成功的。我认为这完全不可能,因为Hibernate无法知道记录是否已孤立。它可以检查是否有任何其他类与子类相关,但它会假设它知道整个DB结构,但情况可能并非如此 然而,你并不是完全不走运。通过将IList接口与您创建的自定义iCascadeletechild接口结合使用,您可以提出一个无缝的解决方案。以下是基本步骤
我知道这看起来很痛苦,但一旦完成,这些接口应该很容易移植。与其公开
IList
,不如通过以下方法控制对集合的访问:
RemoveChild(Child child)
{
Children.Remove(child);
child.Parent = null;
child.Type.RemoveChild(child);
}
Type.RemoveChild看起来很相似,但您必须小心,不要将其放入调用彼此的RemoveChild方法的无限循环中。我相信这可能促使我走上了正确的道路,障碍是:在存储库模式中设置它(即,在这种情况下,child Delete方法将调用自己的存储库方法)并且还能够在不同的会话上下文(即CallSessionContext与WebSessionContext)中使用此功能
RemoveChild(Child child)
{
Children.Remove(child);
child.Parent = null;
child.Type.RemoveChild(child);
}