Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/275.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# NHibernate:呼叫。删除集合上的所有内容_C#_Nhibernate_Fluent Nhibernate - Fatal编程技术网

C# NHibernate:呼叫。删除集合上的所有内容

C# NHibernate:呼叫。删除集合上的所有内容,c#,nhibernate,fluent-nhibernate,C#,Nhibernate,Fluent Nhibernate,在通过NHibernate检索集合时,我遇到无法使用.RemoveAll的问题 我有一个名为Order的实体,我通过NHibernate保存它 订单有许多订单项。以下是我对此关系的映射: mapping.HasMany(o => o.Items) .Cascade.AllDeleteOrphan() .AsList() .Inverse(); 在我的域中,如下所示: publ

在通过NHibernate检索集合时,我遇到无法使用
.RemoveAll
的问题

我有一个名为
Order
的实体,我通过NHibernate保存它

订单
有许多
订单项
。以下是我对此关系的映射:

mapping.HasMany(o => o.Items)
                   .Cascade.AllDeleteOrphan()
                   .AsList()
                   .Inverse();
在我的域中,如下所示:

public virtual IList<OrderItem> Items { get; set; }
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);
    }
}
它不起作用,因为IList没有这个方法

我试过:

items.ToList().RemoveAll(x => x.Variant.VariantSku == variantSku);
但这似乎不起作用。我意识到
items.ToList()
实际上创建了原始列表的副本,因此我想我可以尝试:

var itemsList = items.ToList();
itemsList.RemoveAll(...)
但它是否仍然通过NHibernate持续存在


我的问题:在这种情况下,我是否可以使用
.RemoveAll
,或者我是否应该考虑以不同的方式删除项目?

您始终可以创建自己的
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);
        }
    }
}
publicstaticvoidremoveall(此IList源,谓词)
{
//TODO:参数非空性验证
//优化
列表=源作为列表
如果(列表!=null)
{
list.RemoveAll(谓词);
返回;
}
//慢行
对于(int i=source.Count-1;i>=0;i--)
{
if(谓词(源[i]))
{
资料来源:RemoveAt(i);
}
}
}
我希望NHibernate关心收藏本身——仅仅从
列表中删除一个项目是NHibernate无法“注意到”的


当然,如果您不想让NHibernate关心您所做的事情—如果您的更改只是本地的—那么您的最后一段代码就可以了。

您将集合映射为关系的反面,因此,除了从集合中删除项目外,还必须在OrderItem端取消对订单的引用。因此,RemoveAll方法或扩展方法无法完成此任务

我会这样处理:

public virtual IList<OrderItem> Items { get; set; }
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);
    }
}

我还建议使用集合而不是包映射。

Aha,因此标记“C#”吸引了伟大的Jon Skeet,也就是堆栈大师,他自己。。。很高兴知道:)。。。我确实需要NHibernate知道是否关心此操作。@autonomatt:在这种情况下,假设返回的集合乐于使用
RemoveAt
删除项,这应该可以。我不确定您是否需要item.Order=null(如果您在映射中有.Cascade.AllDeleteOrphan()),是吗?这不是AllDeleteOrphan()的功能吗?不过,其余的都是恰到好处的。我犯了一个小学生的错误,就是对项目进行了预处理并试图删除。item.Order=null使其成为孤立项,否则在刷新会话时会重新保存。实际上,您的代码不起作用。您仍然会收到一个异常:“集合已修改;枚举操作可能无法执行。”我最终使用了for循环。ToArray应将元素复制到新数组中,以防止出现您看到的错误。