首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >连接子类集合的fluent-nhibernate级联删除

连接子类集合的fluent-nhibernate级联删除
EN

Stack Overflow用户
提问于 2014-08-06 12:15:05
回答 1查看 2.1K关注 0票数 2

这里有一个具有父类的模型,它包含一个子类集合(使用TablePerSubClass继承)。当试图通过只对父对象调用delete来测试级联删除时,我会在子表及其连接子类表之间得到一个约束错误。来证明..。

代码语言:javascript
复制
    public class ParentMap : ClassMap<Parent> {
        public ParentMap() {
            Id(x => x.Id);
            HasMany(x => x.Children)
                .Cascade.AllDeleteOrphan()
                .ForeignKeyCascadeOnDelete()
                .Inverse();
        }
    }

    public class ChildMap : ClassMap<Child> {
        public ChildMap() {
            Id(x => x.Id);
            References(x => x.Parent).Not.Nullable();
        }
    }

    public class ExtendedChildMap : SubclassMap<ExtendedChild> {
        public ExtendedChildMap() {
            Map(x => x.extraFeature);
        }
    }

当用以下代码进行单元测试时..。

代码语言:javascript
复制
using (var session = sessionFactory.OpenSession()) {
    using (var transaction = session.BeginTransaction()) {

        var p = new Parent();
        var c1 = new Child() { Parent = p };
        var c2 = new ExtendedChild() { Parent = p };

        session.SaveOrUpdate(p);
        session.SaveOrUpdate(c1);
        session.SaveOrUpdate(c2);
        Assert.IsTrue(session.Query<Parent>().Count() == 1);
        Assert.IsTrue(session.Query<Child>().Count() == 2);
        Assert.IsTrue(session.Query<ExtendedChild>().Count() == 1);

        session.Delete(p);
        Assert.IsTrue(session.Query<Parent>().Count() == 0);
    }
}

测试在最后的断言中失败。

代码语言:javascript
复制
The DELETE statement conflicted with the REFERENCE constraint "FKDB46742824B330ED". The conflict occurred in database "testDB", table "dbo.ExtendedChild", column 'Child_id'

如果集合只包含baseclass子对象,它将按预期工作,但是当添加派生ExtendedChild时,delete似乎与baseclass不一致。感觉好像我在这里错过了一些显而易见的东西,但在搜索了很长时间之后,我仍然没有解决这个问题。

最后,我还不完全清楚Cascade.AllDeleteOrphanForeignKeyCascadeOnDelete之间的功能差异。或者更准确地说(忽略保存/更新部分),前者不处理的情况是什么,并要求指定后者?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-08-07 09:10:32

具有引用约束的问题与我们没有正确地设置父-子关系这一事实有关。

一.不仅儿童应该/必须了解父母,而且父母也必须了解其子女:

代码语言:javascript
复制
var p = new Parent();
// assign parent to children
var c1 = new Child() { Parent = p };
var c2 = new ExtendedChild() { Parent = p };
// assign children to parent as well
p.Children.Add(c1);
p.Children.Add(c2);

上面的代码和带有级联的映射足以让NHibernate只调用:

代码语言:javascript
复制
session.SaveOrUpdate(p);

还有父母pc1和ExtendedChild c2 ..。一切都会持续下去。

如果我们在one连续会话中,则可以删除父p的现有实例:

代码语言:javascript
复制
session.Delete(p) 

这也将触发删除所有的孩子-因为父母确实知道他们:并为他们调用级联.

级联必须仅由NHibernate驱动,而不是由DB驱动。

我们还必须删除ForeignKeyCascadeOnDelete,它有效地创建了带有Server本机级联的DB脚本.在这种情况下,这是不必要的。

代码语言:javascript
复制
HasMany(x => x.Children)
    ...
    // good and very helpful setting Cascade
    .Cascade.AllDeleteOrphan()

    // this is not what we want
    // we do not need cascade on SQL Server side
    // .ForeignKeyCascadeOnDelete()

单元测试:

最好的方法,如何使上述测试充分发挥作用是分裂的创建和删除。为此,我们应发布:

  • Flush(),以确保会话确实持久化所有更改
  • Clear()从一个新的干净表开始

这个结构可以是这样的:

代码语言:javascript
复制
// as above... create Parent and Children - assign each to other
// and call parent to save
session.SaveOrUpdate(p);

// now we have to be sure, that the session will propagate 
// all the changes into the DB
session.Flush();

// and reset all the settings:
session.Clear();

// now (re)load the parent to later let NHiberante do the correct cascade
var parentReloaded = session.Get<Parent>(p.Id);

// Delete all the related stuff
session.Delete(parentReloaded);

如果约束与我们新创建的孩子有关,这将完成任务.

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25160155

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档