加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 是否可以Cascade.All()除了删除?

发布时间:2020-12-15 22:00:48 所属栏目:百科 来源:网络整理
导读:我分别得到一个对象列表(而不是NHibernate),并设置父对象IEnumerable等于这个返回的对象.最初,我们只需要阅读对象.然后我们需要只更新父项的特定字段.最近,我们需要更新孩子的字段.到目前为止,SaveOrUpdate()一切都很顺利.现在,即使将子集合附加到分离的父对
我分别得到一个对象列表(而不是NHibernate),并设置父对象IEnumerable等于这个返回的对象.最初,我们只需要阅读对象.然后我们需要只更新父项的特定字段.最近,我们需要更新孩子的字段.到目前为止,SaveOrUpdate()一切都很顺利.现在,即使将子集合附加到分离的父对象(不使用NHibernate),我也需要更新子节点.以下代码导致父更新,但不是子项.如果我做了所有,那么如果父母没有集合,孩子将被删除.我不想这样做,因为我担心遗留的使用不会解释这种行为.

期望的行为:
?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()时删除是级联的,所以这不是一个大问题,因为我没有改变现有的功能.我仍然希望能够更新所有级联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没有删除孩子们.它使他们与父母脱离关系.

解决方法

更新,反映查询更改

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

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

让我解释一下发生了什么,让我使用一些虚拟语言(注意我使用父母和孩子来简化)

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

我们可以看到,由于映射保存更新,NHibernate通过删除引用确实处理了这种情况.实际上通过UPDATing子表

4)再次加载Parent

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

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

摘要:
正如我们在上面看到的那样,NHibernate正在做着映射和预期的事情.没有删除.只是更新,删除引用

这个答案的上一部分

答案是:改变你的公共int?保存(…)实施. 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概念不起作用.因为:

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()方法,做两个操作:

>更新父级>找到“孩子”或更好 – 与某种程度相关的项目.加载它们调整它们,并调用session.Flush().对ISession引用的对象的任何更改都将保留.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读