6

IQueryableタイプの拡張メソッドを作成しました。これは、エンティティのサブセットを取得し、いくつかの基準でそれらをフィルタリングします。私の問題は、すべてを最初に初期化しないと、変数で構成されたユニオン式を返すことができないことです。aprearsとしてのnull値は無効です。

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

提示されたコードブロックはさらにいくつかの一部であり、それぞれがデータのサブセットを生成し、次の方法で後続のフィルタリングメソッドに伝達されます。

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

2 に答える 2

3

引数の1つがnullの場合は、Unionを呼び出さないでください。

あなたにとって「nullクエリ」とはどういう意味ですか?「行なし」を意味する場合は、それを結合しないでください。「すべての行」を意味する場合は、基になるフィルタリングされていないクエリを取得できるため、結合する必要はありません。

このような:

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

これは、LINQ-to-Objectsを使用してLINQ-to-SQLクエリを作成しています。

新しいバージョン:

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

SQL Serverクエリオプティマイザは、最初のダミークエリを削除して、実行時のコストをまったくかけないようにします。

于 2012-06-16T21:52:32.480 に答える
1
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;
}
于 2012-06-17T04:37:43.357 に答える