How should I initialize IQueryable variables before using Union expression?

I created an extension method of type IQueryable, which takes a subset of objects and filters them according to some criteria. My problem is that I cannot return Union expression from variables without being initialized first. Invalid values, like signatures, are invalid.

public static IQueryable<Person> FilterHairColors(this IQueryable<Person> subQuery, string[] hairColors) { IQueryable<Person> q1 = null; IQueryable<Person> q2 = null; IQueryable<Person> q3 = null; IQueryable<Person> q4 = null; foreach (var value in hairColors) { switch (value) { case "1": q1 = subQuery.Where(p => p.HairColor_bright == true); break; case "2": q2 = subQuery.Where(p => p.HairColor_brown == true); break; case "3": q3 = subQuery.Where(p => p.HairColor_dark == true); break; case "4": q4 = subQuery.Where(p => p.HairColor_red == true); break; } } return q1.AsQueryable().Union(q2.AsQueryable()).Union(q3.AsQueryable()).Union(q4.AsQueryable()); } 

The presented code block is part of several more, and each of them creates a subset of the data transmitted to the next filtering method as follows:

 results = persons.FilterGender(vm.gender).FilterAge(vm.age).FilterHeight(vm.height)...... 
+6
source share
2 answers

Do not call Union when one of the arguments is null.

What does “zero request” mean to you? If this means “no lines”, just don't combine it. If this means “all rows,” you don’t need to concatenate because you can just take a basic, unfiltered query.

Like this:

 var result = new [] { q1, q2, q3, q4, }.Where(query => query != null).Aggregate(Queryable.Union); 

This is using LINQ-to-Objects to build a LINQ-to-SQL query.

A new version:

 var result = dataContext.Persons.Where(_ => false); if(q1 != null) result = result.Union(q1); if(q2 != null) result = result.Union(q2); if(q3 != null) result = result.Union(q3); if(q4 != null) result = result.Union(q4); 

The SQL Server Query Optimizer will delete the first dummy query, so it has no time to start up at all.

+3
source
 public static IQueryable<Person> FilterHairColors(this IQueryable<Person> subQuery, string[] hairColors) { var result = new Person[] { }.AsQueryable(); var contains = new Dictionary<string, Expression<Func<Person, bool>>>(); contains.Add("1", p => p.HairColor_bright); contains.Add("2", p => p.HairColor_brown); contains.Add("3", p => p.HairColor_dark); contains.Add("4", p => p.HairColor_red); foreach (var color in hairColors) { result = subQuery.Where(contains[color]).Union(result); } return result; } 
+1
source

Source: https://habr.com/ru/post/918259/


All Articles