你在这里有几个问题。
第一个是 ToList() 将返回与数据库中的 Where 子句匹配的所有项目。您不能执行 ToList() 并且不能立即执行查询。
第二,你回来了IEnumerable<ItemModel>
。IEnumerables 也立即执行查询。IQueryable<ItemModel>
如果要向返回的类型添加其他参数,则必须返回一个。
第三,使用 Constructor 参数可能很难做到这一点,因为这需要在代码中而不是在数据库中进行处理。 @dasblinkenlight 的解决方案可能有效,但我无法对其进行测试。我猜他知道他在说什么。
您需要将他的代码更改为:
public IQueryable<ItemModel> GetAll()
{
return this.DataLayer.GetNewsItems()
.Where(i => i.IsActive)
.Select((v,i) => new ItemModel(i));
}
编辑:
如果您坚持为您的投影类型使用构造函数参数,那么您将不得不在某处妥协,例如将过滤器传递给您的方法。
像这样的东西:
public IEnumerable<ItemModel> GetItemsByDate(DateTime date)
{
return this.DataLayer.GetNewsItems()
.Where(i => i.IsActive && i.Date == date)
.AsEnumerable()
.Select(x => new ItemModel(x));
}
当您调用该方法时,这仍将执行查询(您不能对输出应用更多过滤器并让它在数据库中执行),但它只会返回与 IsActive 和 Date 过滤器匹配的对象。
您还可以像这样应用任意表达式:
public IEnumerable<ItemModel> GetItemsByDate(Expression<Func<SomeWeirdItemModel,bool>> filter)
{
return this.DataLayer.GetNewsItems()
.Where(i => i.IsActive && filter)
.AsEnumerable()
.Select(x => new ItemModel(x));
}
然后你可以简单地这样做:
var items = DataLayer.GetAll(x => x.Date == date);
var others = DataLayer.GetAll(x => x.Date == date && x.Title.Length > 5 && x.Test = "X");
// etc..
不幸的是,您将不得不在参数中公开 SomeWeirdModel,因为表达式必须对其进行过滤,否则您将不得不做很多工作来尝试翻译过滤器。