【问题标题】:NHibernate: simple delete orphan scenario not workingNHibernate:简单的删除孤立场景不起作用
【发布时间】:2009-09-24 22:04:32
【问题描述】:

我正在尝试使用 NHibernate 建立一个简单的一对多关系/层次结构。我希望自动删除孤儿,但我目前这样做的尝试都会导致 ObjectDeletedException。我想知道是否有人可以告诉我我做错了什么。

编辑:

我应该指定我正在加载一个根 Foo,然后在会话之外删除一个孩子,导致一个或多个孩子成为孤儿。当我随后在第二个会话中调用 SaveOrUpdate(root) 时发生异常。如何纠正分离和修改对象与数据库中持久化对象之间的子列表差异?

有问题的示例代码如下所示:

Foo foo = new Foo();
Foo child1 = new Foo();
Foo child2 = new Foo();

foo.Children.Add(child1);
child1.Children.Add(child2);

// session #1
session.SaveOrUpdate(foo);

// so far, so good

// outside of any session
foo.Children.Clear();

// session #2
PutFoo(foo); // results in ObjectDeletedException

被持久化的对象:

class Foo
{
    private IList<Foo> children = new List<Foo> children;

    public virtual int Id { get; private set; }
    public IList<Foo> Children
    {
        get { return children; }
        set { children = value; }
    }
}

FluentNHibernate 映射:

class FooMap : ClassMap<SyncDir>
{
    public FooMap()
    {
        Id(x => x.Id);
        base.HasMany(x => x.Children).Cascade.AllDeleteOrphan();
     }
}

用于持久化Foo类型对象的方法:

void PutFoo(Foo foo)
{
    using (var session = factory.OpenSession())
    using (var transaction = factory.BeginTransaction())
    {
        session.SaveOrUpdate(foo);
        transaction.Commit();
    }
}

【问题讨论】:

    标签: c# sql nhibernate fluent-nhibernate cascade


    【解决方案1】:

    我一直在做的,是建立双向关系。

    因此,这意味着子项具有对其父项的引用。 从集合中删除子时,我还将对父级的引用设置为 NULL。

    在映射中,您还必须指出关系的“反向”端。 我也从不在课堂外“按原样”公开集合。

    因此,我大多是这样:

    public class Foo
    {
       private ISet<Bar> _bars = new HashSet<Bar>();
    
       public ReadOnlyCollection<Bar> Bars { get return new List<Bar>(_bars).AsReadOnly(); }
    
       public void AddBar( Bar b )
       {
          b.Parent = this;
          _bars.Add (b);
       }
    
       public void RemoveBar( Bar b )
       {
          b.Foo = null;
          _bars.Remove (b);
       }
    }
    
    
    public class Bar
    {
         public Foo Parent { get; set; }
    }
    

    然后,在映射中,我在集合上设置了“反向”端。 因此,这意味着在我的映射中(我仍然使用 xml 文件来指定映射),我在 Foo 类的 Bars 集合上设置了 inverse=true 属性。

    【讨论】:

    • 我添加了 Parent 和 Add()/Remove() 方法,但在删除子节点后在根节点上调用 SaveOrUpdate() 时仍然出现异常。我应该提到我加载了根,然后在会话之外调用 Remove()。只有当移除一个孩子并从第二个会话中调用 SaveOrUpdate() 时才会发生异常。
    猜你喜欢
    • 2012-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多