我想在Linq语句中动态生成跨多个表跨多个表的谓词。在下面的代码片段中,我想使用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
答案 0 :(得分:6)
我认为你的问题是你的PredicateBuilder的类型T - 你的谓词的一半如果作用于Foo,另一半是在吧。
您可以使用简单的手动构造查询替换它:
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
}