我试图查询Netflix OData Feed。我有以下查询在LinqPad中正常工作:
from g in Genres
from t in g.Titles
where g.Name == "Horror" && t.AverageRating == 2 && t.ReleaseYear == 2004
select t
但是,当我将其移动到我的Silverlight应用程序时,用户选择要搜索的内容,因此我可能会或可能不会拥有所有参数。既然如此,我需要在运行时构造查询。我看过动态查询的东西,这样做会很好......我遇到的问题是我需要一个初始可接受的查询来附加,但这不会飞:
from g in Genres
from t in g.Titles
select t;
任何额外的想法将不胜感激。 提前致谢
答案 0 :(得分:1)
如何以旧式,非动态的方式添加过滤器?
var genresQuery = from g in Genres select g;
if ( !string.IsNullOrEmpty( name ) ) genresQuery = genresQuery.Where( g => g.Name == name );
var titlesQuery = from t in genresQuery select t;
if ( !string.IsNullOrEmpty( rating ) ) titlesQuery = titlesQuery.Where( t => t.AverageRating == rating );
if ( !string.IsNullOrEmpty( year ) ) titlesQuery = titlesQuery.Where( t => t.ReleaseYear == year );
答案 1 :(得分:1)
您没有 使用动态查询语法执行此操作,但您可以。
你真的有两个查询,所以你应该建立它们。你可以一次完成所有这些,但是你需要在不同的地方使用两个特定的where子句,一个用于Genres,一个用于标题。请考虑以下模仿您情况的示例。
class Foo
{
public int Id { get; set; }
public string Name { get; set; }
public List<Bar> Bars { get; set; }
}
class Bar
{
public string Color { get; set; }
}
...
List<Foo> foos = new List<Foo>()
{
new Foo() { Id = 1, Name = "Apple", Bars = new List<Bar> () { new Bar() { Color = "Red"}, new Bar() { Color="Green"}} },
new Foo() { Id = 2, Name = "Orange", Bars = new List<Bar> () { new Bar() { Color = "Orange"},new Bar() { Color="Red Orange"}} },
new Foo() { Id = 3, Name = "Banana",Bars = new List<Bar> () { new Bar() { Color = "Yellow"},new Bar() { Color="Green"}} },
new Foo() { Id = 4, Name = "Pear",Bars = new List<Bar> () { new Bar() { Color = "Green"},new Bar() { Color="Yellow"}} }
};
string fooName = "Apple";
string barColor = "Green";
var fooQuery = foos.AsQueryable();
if (!string.IsNullOrEmpty(fooName))
{
string filter = string.Format("Name = \"{0}\"", fooName);
fooQuery = fooQuery.Where(filter);
}
var barQuery = fooQuery.SelectMany(f => f.Bars);
if (!string.IsNullOrEmpty(barColor))
{
string filter = string.Format("Color = \"{0}\"", barColor);
barQuery = barQuery.Where(filter);
}
首先,它为Foos构建了一个查询。如果需要过滤(基于fooSearchName变量),它会生成Where子句并将其添加到查询中。之后,它成为返回Bar元素的查询的基础。同样的,如果它需要过滤,则会生成Where子句并将其添加到查询中。
不幸的是,由于在第一步评估了类型推断,因此无法在步骤上构建单个查询。如果您要说var query = foos.AsQueryable();
,则查询已经评估为IQueryable<Foo>
,因此在稍后的语句中添加SelectMany以选择Bars会失败,因为这需要查询为IQueryable<Bar>
。< / p>
在这种情况下,你的手是强制性的,你必须一次构建查询,或者至少到最高和包括SelectMany的部分,最后的Where子句可以在以后添加。所以你可以这样做:
var query = foos.AsQueryable().Where(fooSearchClause).SelectMany(f => f.Bars);
// later
query = query.Where(barSearchClause);
或者您将查询构建为使用另一个查询的查询,如我的示例所示。
无论如何,根据我提供的术语,迭代最终查询会产生一个结果。更改任一搜索变量的内容将导致查询产生不同的结果。