Link to home
Start Free TrialLog in
Avatar of Allan
AllanFlag for United States of America

asked on

Linq crashes with contains

Hi Experts!

Need help with the following Iinq query. The issue is that the query causes a stackover flow error. Is there a better way to write this in Linq?
One option is to gather all 'people' into memory and then do a for loop through 'perToSearch' and see if it can be found in 'people'.
So, there are many records in 'people' (>100K) and 'perToSearch' (>100K), the example below is to simplify the data set.

Here's the code:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTestProject2
{

    internal class Person
    {   public int  PerId;
        public string FirstName;
        public string LastName;
    }

    [TestClass]
    public class UnitTest2
    {
        [TestMethod]
        public void LinqQuery()
        {
            //Arrange
            List<Person> people = new List<Person>()
            {
                new Person() {PerId = 1, FirstName = "Deku", LastName = "Midoriya"},
                new Person() {PerId = 1, FirstName = "Shoto", LastName = "Todoroki"},
                new Person() {PerId = 1, FirstName = "Ochaco", LastName = "Uraraka"},
            };

            List<int> perToSearch = new List<int>() { 1, 2, 3, 4, 5, 6 };

            //Act
            var x = (from p in people
                     where perToSearch.Contains(p.PerId)
                     select p).ToList();
        }
    }
}

Open in new window

Avatar of it_saige
it_saige
Flag of United States of America image

You code works for me, but I would use Any instead:
using System;
using System.Collections.Generic;
using System.Linq;

namespace EE_Q29163344
{
    class Program
    {
        static void Main(string[] args)
        {
            var people = new List<Person>
            {
                new Person { PerId = 1, FirstName = "Deku", LastName = "Midoriya" },
                new Person { PerId = 1, FirstName = "Shoto", LastName = "Tordoroki"},
                new Person { PerId = 1, FirstName = "Ochaco", LastName = "Uraraka" },
                new Person { PerId = 10, FirstName = "Robert", LastName = "Langdon" }
            };

            var ids = Enumerable.Range(1, 6).ToList();

            var filtered = (from p in people
                            where ids.Any(i => p.PerId == i)
                            select p);

            foreach (var person in filtered)
            {
                Console.WriteLine(person);
            }
            Console.ReadLine();
        }
    }

    class Person
    {
        public int PerId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public override string ToString()
        {
            return $"{FirstName} {LastName}";
        }
    }
}

Open in new window

Produces the following output -User generated image-saige-
Avatar of Allan

ASKER

substituting 'people' for my 'context.SomeDbTable' and the 'ids' is list of int with 25K records.

Still getting the stackover flow error.
User generated image
Here's the build setting; pdb file is not being omitted.

User generated image

Any ideas? Thanks!
Hi!
What about:
var x = (from p in people
            from ps in perToSearch
            where ps == p.PerId
            select p).ToList();
did you intend to use the same PerId for all entries?

stackoverflow happens when there is an infinite recursive operation.

Sara
Avatar of Allan

ASKER

Eduard Ghergu, I think I have tried that; but I will try again.

Sara, I don't understand your question. What we want is pull all person in people that has a matching perId to the list of int --  "perToSearch "
Avatar of Allan

ASKER

Eduard Ghergu, if we try to join on perToSearch it cause a stackover error.

I know the size of the data is not a problem because if I do something like this and it doesn't crash:

var x = (from person in context.people
              from id in context.SomeTable on person.PerId equals id.Perid
              from x in context.SomeTableX on id.Perid equals x.Perid
              select person).ToList()
Ok, so it works now?
Avatar of Allan

ASKER

no, what we want to do in this method is to get all person in people where it matches to the list of int.
Avatar of Allan

ASKER

for whatever reason if we use lamda expression it doesn't crash:

var peopleResults = people.Where(p => perToSearch.Any(ps => ps.Equals(p.PerId))).ToList();
ASKER CERTIFIED SOLUTION
Avatar of Allan
Allan
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial