gpt4 book ai didi

c# - Cascade.All() EXCEPT Delete 是否有可能?

转载 作者:行者123 更新时间:2023-11-30 12:46:07 29 4
gpt4 key购买 nike

我正在单独获取一个对象列表(而不是从 NHibernate 获取)并将父对象 IEnumerable 设置为等于此返回的对象。本来,我们只需要读取对象。然后我们只需要更新父级的特定字段。最近,我们需要更新 child 的字段。到目前为止,SaveOrUpdate() 一切正常。现在,即使子集合附加到分离的父对象(不使用 NHibernate),我也需要更新子集合。以下代码导致更新父项,但不更新子项。如果我全部都做,那么如果 parent 没有收藏, children 就会被删除。我不想这样做,因为我担心遗留使用不能解释这种行为。

期望的行为:
1. 级联对集合的任何更改(无论父级是否由 NHibernate 检索)。 2. 即使父级没有子级集合,也不要删除对象。

这可能吗?

这是我们的 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() 时删除是级联的,所以这不是什么大问题,因为我没有更改现有功能。我仍然希望能够更新除删除之外的所有级联。如果可能的话,一个解决方案将非常适合 future 引用。

更新(2/10/2014)

以下是验证当级联为“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");
}

已更新(2014 年 2 月 11 日)- Radim 在下面的回答中是正确的。 NHibernate 没有删除 child 。它解除了它们与父级的关联。

最佳答案

UPDATE,反射(reflect)查询变化

您在查询更新中显示的测试已证明:

If the parent.Children is set to null and persited, it will have NO children - next time accessed.

让我解释一下发生了什么,让我使用一些虚拟语言(注意我使用 Parent Children 来简化它)

1) 父子映射是cascade="save-update"
这是 NHibernate 的一个信息,在创建或修改期间,子集合应该通过 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

正如我们所见,由于映射 save-update , NHibernate 确实通过删除引用来处理这种情况。事实上通过更新子表

4) 加载 Parent再次

parent = session.Get<Parent>(1);

// EMPTY -- is true: IsEmpty()
Assert.IsTrue(parent.Children.IsEmpty());

总结:正如我们在上面看到的,NHibernate 正在执行映射和预期的操作。没有删除。只是更新,删除引用

这个答案的前一部分

答案是:改变你的public int? Save(...)执行。 NHibernate 级联按预期工作,请在此处阅读更多信息 Ayende, NHibernate Cascades: the different between all, all-delete-orphans and save-update

先看一下上面的语句:

DESIRED BEHAVIOR:
1) Cascade any changes to the collection (whether in the parent was retrieved by NHibernate or not).
2) Do not delete objects even if the parent does not have a collection of children.

粗体部分是原因,为什么 Cascade concept不管用。因为:

Cascade makes sense only if an operation on
the existing parent is cascaded / repeated / passed
the existing/known child(children)

NHiberante 级联实现确实以这种方式工作:9.9. Lifecyles and object graphs (摘录)

Mapping ... with cascade="all" marks the association as a parent/child style relationship where save/update/deletion of the parent results in save/update/deletion of the child(ren). ... A child which becomes unreferenced by its parent is not automatically deleted, except in the case of a <one-to-many> association mapped with cascade="all-delete-orphan"...

不仅没有删除。如果未被引用,则不会触发任何类型的级联操作。

建议:

调整 Save()方法,做两个操作:

  1. 更新父级
  2. 找到“ child ” 或更好的 - 以某种方式相关的项目。加载它们调整它们,然后调用 session.Flush() . ISession 引用的对象的任何更改都将被保留。

关于c# - Cascade.All() EXCEPT Delete 是否有可能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21391810/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com