简体   繁体   中英

False “Sequence contains no elements” exception when using Single()

I seem to be having an issue with a false exception thrown when using .Single() in a Linq statement. Checking the debugger I found that my list does contain the element I am looking for and the id field matches. The code that throws the exception is

public ActionResult Details(int id = 0)
{
    FilterQueue filterqueue = db.FilterQueues.Single(f => f.FilterQueueId == id);

    if (filterqueue == null)
    {
        return HttpNotFound();
    }
    return View(filterqueue);
}

However, switching to a more verbose coding style works. Like this:

public ActionResult Details(int id = 0)
{
    FilterQueue filterqueue = null;
    foreach (var f in db.FilterQueues)
    {
        if (f.FilterQueueId == id) filterqueue = f;
    }
    if (filterqueue == null)
    {
        return HttpNotFound();
    }
    return View(filterqueue);
}

Funnily enough, if I let the code just run past the exception, it does grab the correct item to display the details of.

Now, of course, I can switch the Single to SingleOrDefault and that works fine; However, since the first code block is what is written automatically by the framework, I want to understand what I am doing wrong. If I am making a systematic mistake, I would like to correct it the right way.

I think you are looking for SingleOrDefault() .

In your code, you are checking for null , when null could never be the result of Single();

Here's what you want:

public ActionResult Details(int id = 0)
{
    FilterQueue filterqueue = db.FilterQueues.SingleOrDefault(f => f.FilterQueueId == id);

    if (filterqueue == null)
    {
        return HttpNotFound();
    }

    return View(filterqueue);
}

In your first code, Single would never return null , If there are no matching elements found then it would throw an exception.

"Sequence contains no element"

You need SingleOrDefault which would return null if no element is found.

Your second code block which is using the loop is not an equivalent representation of Single . Enumerable.Single will throw the exception if more than one elements are returned matching the criteria. Your loop, however is returning the last matched item. There could be multiple items in the list but you will never know about it. Your loop is more similar to LastOrDefault

foreach (var f in db.FilterQueues)
{
    if (f.FilterQueueId == id) filterqueue = f;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM