Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/256.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否可以级联.All(),删除除外?_C#_Nhibernate_Nhibernate Mapping - Fatal编程技术网

C# 是否可以级联.All(),删除除外?

C# 是否可以级联.All(),删除除外?,c#,nhibernate,nhibernate-mapping,C#,Nhibernate,Nhibernate Mapping,我将分别获得一个对象列表(而不是从NHibernate获得),并将父对象IEnumerable设置为等于此返回对象。最初,我们只需要读取对象。然后,我们只需要更新父级上的特定字段。最近,我们需要更新孩子的字段。到目前为止,SaveOrUpdate()一切顺利。现在,我需要更新子对象,即使子对象集合附加到分离的父对象(不使用NHibernate)。下面的代码会更新父级,但不会更新子级。如果我全部执行,则如果父对象没有集合,则子对象将被删除。我不想这样做,因为我担心这种行为的遗留用途 期望的行为:

我将分别获得一个对象列表(而不是从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()
更新可以工作,但也会删除。我想消除删除功能

更新(1/27/2014):

我刚刚验证了当映射为
SaveUpdate()
时,删除是级联的,因此这不是一个大问题,因为我没有更改现有的功能。我仍然希望能够更新除删除之外的所有级联。如果可能的话,一个解决方案将是未来的参考

更新(2/10/2014)

以下是验证级联为“SaveUpdate()”时是否删除子级的测试。
GetDocumentFieldDTOWithADO(DocumentFieldID)
使用与NHibernate相同的事务,第一次调用(保存前)时有318个DocumentFieldOrg,保存后调用时有0个DocumentFieldOrg。也许考试有问题?它会因为我调用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没有删除这些孩子。它将它们与父项解除关联。

更新,反映查询更改

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

如果
parent.Children
设置为
null
并被分配,则它将没有子级-下次访问

让我解释一下发生了什么,让我使用一些虚拟语言(请注意,我正在使用
家长
孩子
来简化)

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
以下是执行的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 = session.Get<Parent>(1);

// EMPTY -- is true: IsEmpty()
Assert.IsTrue(parent.Children.IsEmpty());
parent=session.Get(1);
//EMPTY——为true:IsEmpty()
Assert.IsTrue(parent.Children.IsEmpty());
总结: 正如我们在上面看到的,NHibernate正在做映射和预期的事情。没有删除。只是更新,删除引用

这个答案的前一部分

答案是:更改您的
public int?保存(…)
实现。NHibernate级联按预期工作,请在此处阅读更多内容

首先看一下上面的陈述:

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

粗体部分是
级联概念
不起作用的原因。因为:

只有在
现有的父级被级联/重复/传递
现有/已知的子项(子项)

NHiberante级联实现实际上是这样工作的:(摘录)

映射。。。with
cascade=“all”
将关联标记为父/子样式的关系,其中父项的保存/更新/删除将导致子项(ren)的保存/更新/删除未被其父级引用的子级不会自动删除,但使用cascade=“all delete orphan”映射的关联除外

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

建议:

调整
Save()
方法,以执行两个操作:

  • 更新父项
  • 找到“孩子们”或更好的——某种程度上相关的项目。加载它们并调整它们,然后调用
    session.Flush()
    。ISession引用的对象上的任何更改都将被持久化

  • 我不明白你的回答。如果父POCO对象没有任何子POCO对象,NHibernate将从数据库中删除子记录。我可以在save实现中实现子项的更改管理,但我希望NHibernate处理对象映射和更改管理。我想我希望有一些映射或SaveUpdate/Merge方法的实现,可以指示NHibernate更新记录,但永远不要删除对象。你可以很好地控制你可以更新什么,但不能控制删除什么。也许我不理解你的问题。级联是这样工作的:1)必须有传递给会话的父级(SaveOrUpdate(parent)2)任何子级都将按此处所述进行级联。3) 如果出现
    save udpate
    delete,将永远不会发出。4) 在“全部”的情况下,将删除
    parent = session.Get<Parent>(1);
    
    // EMPTY -- is true: IsEmpty()
    Assert.IsTrue(parent.Children.IsEmpty());