NHibernate删除子集合对象StaleObjectStateException

时间:2014-02-23 22:55:17

标签: c# nhibernate

我遇到了NHibernate的问题,我无法找到最佳解决方案。 我有一个带有子集合的Customer类,我试图通过从列表中删除它来删除集合中的项目。

类和映射如下:

public class Customer : Entity<Customer>
{
    public virtual IList<WishlistProduct> Wishlist { get; set; }

    public Customer()
    {
        Wishlist = new List<WishlistProduct>();
    }

    public virtual bool RemoveFromWishlist(int id)
    {
        bool removed = false;

        for (int x = Wishlist.Count - 1; x >= 0; x--)
        {
            if (Wishlist[x].Product.Id == id)
            {
                Wishlist[x].Customer = null;
                Wishlist.RemoveAt(x);
                removed = true;
            }
        }

        return removed;
    }
}

映射:

internal class CustomerMapping : EntityMapping<Customer>
{
    internal CustomerMapping()
    {
        HasMany(x => x.Wishlist)
            .Inverse()
            .Cascade.AllDeleteOrphan();
    }
}

internal class WishlistProductMapping : EntityMapping<WishlistProduct>
{
    internal WishlistProductMapping()
    {
        References(x => x.Customer);
    }
}

要删除孩子我正在做这样的事情:

customer.RemoveFromWishlist(1);

我使用以下会话管理技术:

builder.Register(x => MyApplication.SessionFactory.OpenSession()).As<ISession>()
            .InstancePerHttpRequest()
            .OnRelease(x =>
            {
                x.Flush();
                x.Close();
            });

我可以从SQL日志中看到,这确实生成了正确的DELETE语句来删除记录,但是在OnRelease回调中我得到了一个StaleObjectStateException:&#34; Row被另一个事务更新或删除(或未保存) - 值映射不正确)&#34;。在异常细节中,我可以看到它正在被删除的子对象上进行borking。

为什么会这样?在调用Flush之前,我没有看到子对象是如何被修改的。我没有对父对象或子对象做任何事情,除了从列表中删除子对象。

我知道我可以单独删除子对象,但是业务逻辑似乎更自然,能够从父列表中删除子项并删除删除。

感谢任何帮助或见解,谢谢。

2 个答案:

答案 0 :(得分:1)

除了@jackie-ide答案。

在这种情况下你使用了错误的cascade type。你需要使用AllDeleteOrphan():

internal class CustomerMapping : EntityMapping<Customer>
{
    internal CustomerMapping()
    {
        HasMany(x => x.Wishlist)
            .Inverse()
            .Cascade.AllDeleteOrphan();
    }
}

答案 1 :(得分:0)

您需要通过从集合中删除项目并忽略对其父项的引用来维护关系的两个方面。

public virtual bool RemoveFromWishlist(int id)
{
    bool removed = false;

    for (int x = Wishlist.Count - 1; x >= 0; x--)
    {
        if (Wishlist[x].Product.Id == id)
        {
            Wishlist[x].Customer = null;
            Wishlist.RemoveAt(x);
            removed = true;
        }
    }

    return removed;
}