c# – 是否可以Cascade.All()除了删除?
我分别得到一个对象列表(而不是NHibernate),并设置父对象IEnumerable等于这个返回的对象.最初,我们只需要阅读对象.然后我们需要只更新父项的特定字段.最近,我们需要更新孩子的字段.到目前为止,SaveOrUpdate()一切都很顺利.现在,即使将子集合附加到分离的父对象(不使用NHibernate),我也需要更新子节点.以下代码导致父更新,但不是子项.如果我做了所有,那么如果父母没有集合,孩子将被删除.我不想这样做,因为我担心遗留的使用不会解释这种行为.
期望的行为: 这可能吗? 这是我们的NHibernate保存方法: [Transaction] public int? Save(DocumentFieldDTO entity,bool autoFlush) { var persisted = CurrentSession.Merge(entity); entity.DocumentFieldID = persisted.DocumentFieldID; if (autoFlush) { CurrentSession.Flush(); } return entity.DocumentFieldID; } DocumentFieldDTOMap看起来像这样: public class DocumentFieldDTOMap : EntityMapBase { public DocumentFieldDTOMap() { Table("DocumentField"); Id(m => m.DocumentFieldID).GeneratedBy.Increment().UnsavedValue(null); Map(x => x.Name); Map(x => x.DocumentSectionID).Not.Update(); // .... Lots of other fields ....// HasMany(x => x.DocumentFieldOrgs) .Cascade.SaveUpdate() .LazyLoad() .KeyColumn("DocumentFieldID"); } } } 如果我将Cascade.SaveUpdate()更改为Cascade.All(),则更新会起作用,但也会删除.我想消除删除功能. 更新(2014年1月27日): 我刚刚验证了当映射是SaveUpdate()时删除是级联的,所以这不是一个大问题,因为我没有改变现有的功能.我仍然希望能够更新所有级联EXCEPT删除.如果可能的话,解决方案将非常适合将来参考. 更新(2014年2月2日) 以下是在级联为“SaveUpdate()”时验证子项被删除的测试. GetDocumentFieldDTOWithADO(DocumentFieldID)使用与NHibernate相同的事务,在第一次调用时(保存前)有318个DocumentFieldOrgs,在保存后调用时有0.也许这个测试存在问题?是否删除了孩子因为我打电话给Merge? [Test] public void Save_ShouldDeleteDocumentFieldOrgs_WhenSavingDocumentFieldWithoutDocFieldOrgsList() { //arrange var expectedDocField = GetDocumentFieldDTOWithADO(DocumentFieldID); expectedDocField.DocumentFieldOrgs = null; //act Repository.Save(expectedDocField,false); SessionFactory.GetCurrentSession().FlushAndEvict(expectedDocField); //assert var actualDocField = GetDocumentFieldDTOWithADO(DocumentFieldID); actualDocField.DocumentFieldOrgs.Should() .BeEmpty("DocumentFieldOrgs should be deleted if the parent does not have a child collection"); } 更新(2/11/2014) – Radim在下面的回答中是正确的. NHibernate没有删除孩子们.它使他们与父母脱离关系. 解决方法
更新,反映查询更改
您在查询更新中显示的测试已经证明:
让我解释一下发生了什么,让我使用一些虚拟语言(注意我使用父母和孩子来简化) 1)父子映射是cascade =“save-update” 2)让我们加载父 var session = ... // get a ISession for our test var parent = session.Get<Parent>(1); // e.g. DocumentFieldDTO // NOT Empty -- is true: IsNotEmpty() Assert.IsTrue(parent.Children.IsNotEmpty()); // e.g. DocumentFieldOrgs 3)现在,删除引用并检查NHibernate将执行的操作: parent.Children = null; session.Flush(); session.Clear(); 这是执行的SQL语句: exec sp_executesql N'UPDATE [schema].[Child_Table] SET ParentId = null WHERE ParentId = @p0',N'@p0 int',@p0=1 我们可以看到,由于映射保存更新,NHibernate通过删除引用确实处理了这种情况.实际上通过UPDATing子表 4)再次加载Parent parent = session.Get<Parent>(1); // EMPTY -- is true: IsEmpty() Assert.IsTrue(parent.Children.IsEmpty()); 摘要: 这个答案的上一部分 答案是:改变你的公共int?保存(…)实施. NHibernate级联按预期工作,请在此处阅读更多内容Ayende,NHibernate Cascades: the different between all,all-delete-orphans and save-update 首先看看上面的陈述:
大胆的部分是原因,为什么Cascade概念不起作用.因为:
NHiberante级联实现确实以这种方式工作:9.9. Lifecyles and object graphs(摘录)
不仅没有删除它.如果未引用,则不会接收任何类型的级联操作的触发器. 建议: 调整Save()方法,做两个操作: >更新父级>找到“孩子”或更好 – 与某种程度相关的项目.加载它们调整它们,并调用session.Flush().对ISession引用的对象的任何更改都将保留. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |