how should I initialize IQueryable variables, before use a Union expression?

给你一囗甜甜゛ 提交于 2019-12-22 05:28:14

问题


I've created an extension method over IQueryable type, which takes a subset of entities and filters them upon some criterrions. My problem is that I can't return a Union expression made of the variables, without all being initialized first. Null values, as aprears, are not valid.

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 produces a subset of data, conveyed to a subsequent filtering method this way:

results = persons.FilterGender(vm.gender).FilterAge(vm.age).FilterHeight(vm.height)......  

回答1:


Don't call Union when one of the arguments is null.

What does a "null-query" mean to you? If it means "no rows" then just don't Union it. If it means "all rows" you don't need to union because you can just take the underlying, 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 construct 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 remove the first dummy query so that it has no runtime cost at all.




回答2:


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


来源:https://stackoverflow.com/questions/11067226/how-should-i-initialize-iqueryable-variables-before-use-a-union-expression

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!