Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sequence contains more than one matching element

Tags:

c#

linq-to-sql

When I am trying to set IsDefault property of each dressing items where match a condition it throws an error saying:

Sequence contains more than one matching sequence.

(this.DressingItems
     .Where(xx => xx.DressingInfo.CatID == catId 
                        && xx.ProductID == this.ProductID)
     .Single()).IsDefault = false;
like image 993
NoviceToDotNet Avatar asked Aug 13 '13 07:08

NoviceToDotNet


4 Answers

Well, this exception says that at least two items of the sequence DressingItems match your Where condition. The call to Single then causes the exception because it asserts that only one item is passed in.

Reading your question makes me think that you want to do something on each item of the input sequence, so you will probably use a foreach loop:

foreach(var item in this.DressingItems.Where(xx => xx.DressingInfo.CatID == catId && xx.ProductID == this.ProductID))
{
    item.IsDefault = false;
}
like image 107
Matten Avatar answered Nov 05 '22 19:11

Matten


this.DressingItems.Where(x=> x.DressingInfo.CatID == catId && 
                                x.ProductID == this.ProductID).ToList()
                 .ForEach(item=>item.IsDefault = false);
like image 31
Damith Avatar answered Nov 05 '22 21:11

Damith


The point of the Single operator is to assert that a given sequence only has one item. For instance when retrieving a specific instance by primary key.

I suppose you want to mutate the state of any DressingItem matching the criteria, in which case you have some options, all involving enumerating the resultset, and executing some behavior.

There is no LINQ operator to specifically do this, since LINQ operators are meant to be pure. Pure functions are functions that do not have side effects, and this is exactly what you are trying to do.

There is, however, an extensionmethod on List<T> which does allow this. e.g.

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

Or you could roll your own:

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;
    }
}

You might ask why the guys at Microsoft decided against adding this to the BCL: As I recall, the idea was that an extensionmethod vs. a foreach() { } construct would not yield much benefits in terms of typing anyway, and it wouldn't help at all in terms of ambiguity. All other operators are side-effect free, and this one is explicitely designed to induce them.

like image 2
Yannick Motton Avatar answered Nov 05 '22 19:11

Yannick Motton


It is an InvalidOperationException thrown by the Single method.

The method is supposed to return only one element, please check the criteria that you use on your query.

However an exception is also thrown when it fails to find any element

like image 1
Rohit Avatar answered Nov 05 '22 20:11

Rohit