2011-03-14 101 views
5

我想动态生成跨Linix语句中的Join的多个表的谓词。在下面的代码片段,我想用PredicateBuilder或类似的结构来代替“其中”语句下面的代码:PredicateBuilder可以生成跨越多个表的谓词吗?

替换:

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

回答

6

我觉得你的问题是你PredicateBuilder的T型 - 你的谓词的一半,如果作用于富,另一半则是在一间酒吧。

你可以用一个简单的手动构造查询替换此:

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而是使之在美孚,酒吧夫妇工作 - 例如

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 
}