为什么有这么多列表/ToLists?IEnumerable/IQueryable 有什么问题?
var eventi = (from Evento ae in new Eventi()
select ae);
if (strNome != "")
{
eventi = eventi.Where(e => e.Titolo.ToLower().Contains(strNome.ToLower()) && e.Titolo != "");
}
if (strComune != "")
{
eventi = eventi.Where(e => e.Comune != null && e.IDComune == strComune);
}
if (strMesi != "")
{
eventi = eventi.Where(e => MesiSelezionati.Contains(DateTime.Parse(e.DataEvento).Month.ToString()));
}
// if you do need a list, then do so right at the end
var results = eventi.ToList();
编辑:澄清Caesay的一些原则
Caesay,感谢您抽出时间来测试实现以确认延迟加载按预期工作;非常感谢!
我想解释为什么我不同意您对上述方法在运行时进行优化而您的在编译时进行优化的评论。
由于缺乏更好的描述,上述方法是预期的方法。这是因为对eventi的分配正确地将表达式附加到 IEnumerable/IQueryable 的源。
您的方法仅受某些提供程序支持,例如 Linq to Entities,它们希望将Func(Of T, TResult)传递给他们的Select、Where等扩展。许多提供者,例如 Entity Framework 和 Linq to Sql 提供者,都提供了IQueryable,它实现了IEnumerable。但是,这里的区别在于IQueryable的Select、Where等希望您传递Expression(Of Func(Of T, TResult))。
在这些情况下,您的代码不会像预期的那样运行(或者至少不会像我预期的那样),因为 Expression 不支持多行 lambda,因为编译器会正确解释我的语句并将它们编译成 Expression>。
举个简单的例子:
public void Test<T1, T2>(System.Linq.Expressions.Expression<Func<T1, T2>> arg)
{
throw new NotImplementedException();
}
public void Test()
{
Test((string x) => x.ToLower());
Test((string x) =>
{
return x.ToLower();
});
}
在上面的例子中,第一个表达式绝对没问题。第二个大致基于您的示例,将失败,但有以下例外:
A lambda expression with a statement body cannot be converted to an expression tree
编译器可能会将您的语句识别为它知道 IEnumerable 支持的Func 。结果将是对数据库的查询将不包括您的任何 Where 表达式,从而返回整个数据源。一旦数据源在内存中,它将应用您的 IEnumerable Where 子句。就个人而言,我更喜欢将这些东西传递给数据库,这样我就不会浪费带宽返回比我需要的更多的数据,并且我可以利用我的数据源功能来过滤可能的数据(并且在 Sql Server 的案例)比在内存中这样做更好。
我希望这是有道理的,对你有用吗?