序列包含多个匹配元素

本文关键字:元素 包含多 | 更新日期: 2023-09-27 18:27:30

当我试图设置与条件匹配的每个敷料项目的IsDefault属性时,它会抛出一个错误:

序列包含多个匹配序列。

(this.DressingItems
     .Where(xx => xx.DressingInfo.CatID == catId 
                        && xx.ProductID == this.ProductID)
     .Single()).IsDefault = false;

序列包含多个匹配元素

这个异常表示序列DressingItems中至少有两个项符合Where条件。对Single的调用会导致异常,因为它断言只传入了一个项

阅读你的问题会让我觉得你想对输入序列的每一项做点什么,所以你可能会使用foreach循环:

foreach(var item in this.DressingItems.Where(xx => xx.DressingInfo.CatID == catId && xx.ProductID == this.ProductID))
{
    item.IsDefault = false;
}
this.DressingItems.Where(x=> x.DressingInfo.CatID == catId && 
                                x.ProductID == this.ProductID).ToList()
                 .ForEach(item=>item.IsDefault = false);

Single运算符的作用是断言给定序列只有一个项。例如,当通过主键检索特定实例时。

我想你想改变任何符合条件的DressingItem的状态,在这种情况下,你有一些选项,所有这些都涉及枚举结果集和执行一些行为。

由于LINQ操作符是纯的,因此没有LINQ操作符专门做这件事。纯函数是没有副作用的函数,这正是你想要做的

然而,List<T>上有一个扩展方法允许这样做。例如

this.DressingItems.Where(di => di.DressingInfo.CatID == catId
                            && di.ProductID == this.ProductID)
                  .ToList()
                  .ForEach(di => 
                  {
                      di.IsDefault = false
                  });

或者你可以推出自己的:

public static class EnumerableExtensions
{
    public static IEnumerable<T> ForEach<T>(
         this IEnumerable<T> source,
         Action<T> mutator)
    {
        var buffered = source.ToList();
        buffered.ForEach(mutator);
        return buffered;
    }
}

你可能会问,为什么微软的人决定不把它添加到BCL中:据我回忆,当时的想法是,扩展方法与foreach() { }构造在打字方面不会产生太多好处,而且在歧义方面也没有任何帮助。所有其他操作符都是无副作用的,而这一个操作符是明确设计用来诱导它们的。

它是由Single方法抛出的InvalidOperationException

该方法应该只返回一个元素,请检查您在查询中使用的条件。

然而,当它未能找到任何元素

时,也会引发异常

您有多个项目。与给定类别Id和产品Id匹配的DressingItems。

如果你确定一定有一个(单身),那么你必须回顾一下这是怎么回事。DressingItems已加载。

如果期望有多个值,那么必须使用foreach来设置值。

由于您正在寻找一个单行,您可以创建自己的方法来实现这一点。

public static void DoActionForEachElement<T>(IEnumerable<T> items, Func<T, bool> predicate, Action<T> action)
{
    foreach (var item in items)
    {
        if (predicate(item))
            action(item);
    }
}

然后通过调用

DoActionForEachElement(
               DressingItems,
               xx => xx.DressingInfo.CatID == catId && xx.ProductID == ProductID,
               x => x.IsDefault = false);

这样就不必先将结果从Where强制转换为List