How can I store linq queries?

Viewed 106

I've researched but I haven't found anything about this situation.

I have two linq queries:

            //checking all columns if there is
            mockDataList = mockDataList.Where(w =>
            w.Email.ToLower().Contains(search)          ||
            w.Gender.ToLower().Contains(search)         ||
            w.Name.ToLower().Contains(search)           ||
            w.Surname.ToLower().Contains(search)        ||
            w.Id.ToString().ToLower().Contains(search)
            ).Skip(start).Take(length).ToList();

            //getting count info
            var filteredTotal = mockDataList.Where(w =>
            w.Email.ToLower().Contains(search) ||
            w.Gender.ToLower().Contains(search) ||
            w.Name.ToLower().Contains(search) ||
            w.Surname.ToLower().Contains(search) ||
            w.Id.ToString().ToLower().Contains(search)
            ).Count();

I want to count before to take 10 of them. Therefore I've had to write two queries. I don't want it to duplicate. How can I store without executing query?

*sorry for my grammar mistakes

3 Answers

Just store LINQ query in the local variable:

var query = mockDataList.Where(w =>
            w.Email.ToLower().Contains(search) ||
            w.Gender.ToLower().Contains(search) ||
            w.Name.ToLower().Contains(search) ||
            w.Surname.ToLower().Contains(search) ||
            w.Id.ToString().ToLower().Contains(search));

var filteredTotal = query.Count();

mockDataList = query.Skip(start).Take(length).ToList();

LINQ queries are executed, when your loop through them via foreach or when you call methods like FirstOrDefault(), ToList(), ToArray(), ... So the following is no problem:

var query = mockDataList.Where(w =>
            w.Email.ToLower().Contains(search)          ||
            w.Gender.ToLower().Contains(search)         ||
            w.Name.ToLower().Contains(search)           ||
            w.Surname.ToLower().Contains(search)        ||
            w.Id.ToString().ToLower().Contains(search)
            ); // nothing is done here, no filtering

mockDataList  = query.Skip(start).Take(length).ToList(); // here, the filtering is done
var filteredTotal = query.Count(); // here, the filtering is done again

I think the better practice would be to store the IEnumerable as suggested by @SomeBody.

IEnumerable<MyClass> query = mockDataList.Where(w => .....);
List<MyClass> PaginatedFilteredItems = query.Skip(start).Take(length).ToList();
int FilteredItemsTotal = query.Count();
// Or
int PaginatedFilteredItemsTotal = PaginatedFilteredItems.Count;

Another approach whould be to use a Func or Expression to store your query:

public class MyClass{
    public int Id;
    public string Email;
    public string Gender;
    public string Name;
    public string Surname;  
}

Func<MyClass, bool> MyClassFunc = w =>
            w.Email.ToLower().Contains(search)          ||
            w.Gender.ToLower().Contains(search)         ||
            w.Name.ToLower().Contains(search)           ||
            w.Surname.ToLower().Contains(search)        ||
            w.Id.ToString().ToLower().Contains(search);

then you could use it like this:

mockDataList = mockDataList.Where(MyClassFunc).Skip(start).Take(length).ToList();
Related