6

LinqステートメントのJoin全体で複数のテーブルにまたがる述語を動的に生成したいと思います。次のコードスニペットでは、PredicateBuilderまたは同様の構造を使用して、次のコードの「where」ステートメントを置き換えます。

交換:

public class Foo
{
    public int FooId;  // PK
    public string Name;
}

public class Bar
{
    public int BarId;  // PK
    public string Description;
    public int FooId;  // FK to Foo.PK
}

void Test()
{
    IQueryable<Foo> fooQuery = null;    // Stubbed out
    IQueryable<Bar> barQuery = null;    // Stubbed out

    IQueryable<Foo> query =
        from foo in fooQuery
        join bar in barQuery on foo.FooId equals bar.FooId
        where ((bar.Description == "barstring") || (foo.Name == "fooname"))
        select foo;
}

次のようなもので:

void Test(bool searchName, bool searchDescription)
{
    IQueryable<Foo> fooQuery = null;    // Stubbed out
    IQueryable<Bar> barQuery = null;    // Stubbed out

    IQueryable<Foo> query =
        from foo in fooQuery
        join bar in barQuery on foo.FooId equals bar.FooId
        select foo;

    // OR THIS

    var query =
        from foo in fooQuery
        join bar in barQuery on foo.FooId equals bar.FooId
        select new {foo, bar};

    var predicate = PredicateBuilder.False<Foo>();
    if (searchName)
    {
        predicate = predicate.Or(foo => foo.Name == "fooname");
    }
    if (searchDescription)
    {
        // Cannot compile
        predicate = predicate.Or(bar => bar.Description == "barstring");
    }
    // Cannot compile
    query = query.Where(predicate);
}

この問題に取り組むための考え、アイデア、戦略はありますか?

ありがとう、

EulerOperator

4

1 に答える 1

6

あなたの問題は、PredicateBuilder の型 T にあると思います。述語の半分は Foo で動作する場合、残りの半分は Bar です。

これを、手動で作成した単純なクエリに置き換えることができます。

void Test()
{
    IQueryable<Foo> fooQuery = null;    // Stubbed out
    IQueryable<Bar> barQuery = null;    // Stubbed out

    IQueryable<Foo> query =
        from foo in fooQuery
        join bar in barQuery on foo.FooId equals bar.FooId
        select new {Foo = foo, Bar = bar};

    if (searchName) 
    {
        query = query.Where(fb => fb.Foo.Name == "fooname");
    }
    if (searchDescription)
    {
        query = query.Where(fb => fb.Bar.Description == "barstring");
    }

    // use query here
}

別の方法は PredicateBuilder を使用することですが、Foo、Bar の組み合わせで機能させることです。

class FooBar
{
   public Foo Foo {get;set;}
   public Bar Bar {get;set;}
}

void Test(bool searchName, bool searchDescription)
{
    IQueryable<Foo> fooQuery = null;    // Stubbed out
    IQueryable<Bar> barQuery = null;    // Stubbed out

    var query =
        from foo in fooQuery
        join bar in barQuery on foo.FooId equals bar.FooId
        select new FooBar
        {
           Foo = foo, 
           Bar = bar
        };

    var predicate = PredicateBuilder.False<FooBar>();
    if (searchName)
    {
        predicate = predicate.Or(foobar => foobar.Foo.Name == "fooname");
    }
    if (searchDescription)
    {
        predicate = predicate.Or(foobar => foobar.Bar.Description == "barstring");
    }
    query = query.Where(predicate);

    // use query here
}
于 2011-03-14T20:02:48.243 に答える