2012-01-27 74 views
2

当通过NHibernate检索集合时,我无法使用.RemoveAllNHibernate:在集合上调用.RemoveAll

我有一个实体叫Order,我坚持通过NHibernate。

Order有很多OrderItems。这是我对这个映射关系:

mapping.HasMany(o => o.Items) 
        .Cascade.AllDeleteOrphan() 
        .AsList() 
        .Inverse(); 

在我的域名看起来像这样:

public virtual IList<OrderItem> Items { get; set; } 

据我了解,我必须使用IList因为NHibernate的有它自己的List实现。

现在我想从我的Order使用此方法在我Order类删除项目:

public virtual void RemoveItem(string variantSku) 
{ 
    items.RemoveAll(x => x.Variant.VariantSku == variantSku); 
} 

它不工作,因为IList没有这个方法。

我想:

items.ToList().RemoveAll(x => x.Variant.VariantSku == variantSku); 

但是,这似乎并没有工作。我意识到items.ToList()实际创建原始列表的副本,所以我想我可以尝试:

var itemsList = items.ToList(); 
itemsList.RemoveAll(...) 

但后来它仍然可以通过NHibernate的坚持?

我的问题:我可以在这种情况下实际使用.RemoveAll吗?或者我应该考虑以不同的方式移除一个项目?

回答

4

您将集合映射为关系的反面,因此除了从集合中删除项目之外,还必须取消对OrderItem一侧的Order的引用。因此,RemoveAll方法或扩展方法不会完成这项工作。

我会处理这样的:

public virtual void RemoveItem(string variantSku) 
{ 
    var itemsToRemove = items.Where(x => x.Variant.VariantSku == variantSku).ToArray(); 
    foreach(var item in itemsToRemove) 
    { 
     item.Order = null; 
     items.Remove(item); 
    } 
} 

我还建议您使用设置而不是包映射。

+0

我不确定你需要item.Order = null,如果你在映射中有.Cascade.AllDeleteOrphan(),是吗?这不正是AllDeleteOrphan()所做的吗?其余的是现货。正在让这名男生犯错误,对项目进行foreach'ing并试图删除。 – autonomatt 2012-01-27 15:10:01

+0

item.Order = null是使它成为孤儿的原因,否则会话刷新时会重新保存。 – 2012-01-27 15:53:41

+0

其实你的代码不起作用。你仍然会得到一个例外:“集合被修改;枚举操作可能无法执行。“我最终使用了for循环。 – autonomatt 2012-01-31 13:33:57

3

你总是可以创建自己的RemoveAll扩展方法:

public static void RemoveAll<T>(this IList<T> source, Predicate<T> predicate) 
{ 
    // TODO: Argument non-nullity validation 

    // Optimization 
    List<T> list = source as List<T> 
    if (list != null) 
    { 
     list.RemoveAll(predicate); 
     return; 
    } 

    // Slow way 
    for (int i = source.Count - 1; i >= 0; i--) 
    { 
     if (predicate(source[i])) 
     { 
      source.RemoveAt(i); 
     } 
    } 
} 

期望 NHibernate的关心集合本身 - 刚刚从List<T>删除项目不是一件NHibernate的可以“的通知”。当然,如果你不希望NHibernate关心你的工作 - 如果你的修改只是意思是是本地的 - 那么你的最后一段代码就没问题了。

+0

啊哈,所以标签“C#”吸引了伟大的Jon Skeet,又名堆栈大师,他本人......很高兴知道:) ......我需要NHibernate来了解关于这个操作的关心。 – autonomatt 2012-01-27 11:44:56

+0

@autonomatt:在这种情况下,假设返回的集合很乐意使用'RemoveAt'去除项目,这应该没问题。 – 2012-01-27 11:55:17