2

我有一个测试代码:

        using (var session = factory.OpenSession())
        {
            var animalsCategory = session.Query<Category>().Where(c => c.Name == "Animals").Single();
            Assert.AreEqual(3, animalsCategory.Products.Count());
            animalsCategory.Products.ForEach(x => session.Delete(x));
            session.Flush();
        }

类别产品类别的映射:

public class ProductMap : ClassMap<Product>
{
    public ProductMap()
    {
        Id(x => x.ID);
        Map(x => x.Name).Not.Nullable().Length(50);
        Map(x => x.Description).Length(4000);
        Map(x => x.UnitPrice).Not.Nullable();
        Map(x => x.ReorderLevel).Not.Nullable();
        Map(x => x.Discontinued);

        References(x => x.Category).Not.Nullable();
    }
}

public class CategoryMap : ClassMap<Category>
{
    public CategoryMap()
    {
        Id(x => x.ID);
        Map(x => x.Name);
        Map(x => x.Description);
        HasMany<Product>(x => x.Products).Inverse().Cascade.AllDeleteOrphan();
    }
}

此外,还有以下课程:

public class Product : Entity<Product>
{
    public virtual string Name { get; set; }
    public virtual string Description { get; set; }
    public virtual Category Category { get; set; }
    public virtual decimal UnitPrice { get; set; }
    public virtual int ReorderLevel { get; set; }
    public virtual bool Discontinued { get; set; }
}

public class Category : Entity<Category>
{
    private List<Product> products = null;

    public virtual string Name { get; set; }
    public virtual string Description { get; set; }
    public virtual IEnumerable<Product> Products { get { return products; } }
}

现在,当我运行测试代码时,我得到一个异常:

N* Hibernate.ObjectDeletedException : 已删除的对象将被级联重新保存(从关联中删除已删除的对象)[Model.Product#1] *

这很好,我想我明白了:)

所以我在Category类中创建了一个方法:

    public virtual void ClearProducts()
    {
        products.Clear();
    }

我已将测试代码更改为以下内容:

        using (var session = factory.OpenSession())
        {
            var animalsCategory = session.Query<Category>().Where(c => c.Name == "Animals").Single();
            Assert.AreEqual(3, animalsCategory.Products.Count());
            //animalsCategory.Products.ForEach(x => session.Delete(x));
            animalsCategory.ClearProducts();
            session.Flush();
        }

我已经用ClearProducts调用替换了ForEach 。现在我得到了例外:

System.IndexOutOfRangeException : System.Collections.Generic.List`1.Clear() 处的 System.Array.Clear(Array array, Int32 index, Int32 length) 处的索引超出了数组的范围

我还使用了while(products.Count >0)循环从集合中删除所有产品,但我也遇到了一个例外。如果我无法从集合中删除子对象,有人可以告诉我如何删除它们吗?

谢谢

编辑1:我惊呆了......我刚刚改变了集合类型(和字段定义):

    private List<Product> products = null;

到:

    private IList<Product> products = null;

并且代码有效。有人可以告诉我为什么吗?

4

1 回答 1

2

问题 #1 - 您不能直接从子集合中删除对象。为了删除它们,您将从 Products 中删除一个项目,然后保存父 Category 对象。因此,在 DDD 术语中,您应该只对聚合根对象执行删除,但您已经弄清楚了。

问题 #2 - 如果您使用延迟加载,您需要在公共实例成员上使用 virtual 关键字并使用接口进行收集,以便 NHibernate 可以用知道如何在首次访问时延迟加载的代理替换您的属性。这是一个类似的问题,有一个很好的答案

Are you sure your Category and CategoryMap classes now look like that? Not sure how would the mapping like you have there work, since you don't have a setter on your public property, nor you have defined different access strategy in mapping.

于 2012-05-31T22:20:58.543 回答