我知道,如果您在 linq 查询中有一些函数没有映射到 sql 查询,那么您必须首先调用 .AsEnumerable() :
var model = _service.GetQuery
.Where(data => data.SomeFlag == true)
.Select(data => new { Foo = CalculateFoo(data.Bar); });
不能由 linq to sql 执行,但通过添加 AsEnumerable() 我们可以使 .Select() 子句由 linq 执行到对象:
var model = _service.GetQuery
.Where(data => data.SomeFlag == true)
.AsEnumerable()
.Select(data => new { Foo = CalculateFoo(data.Bar); });
但是如果数据集非常大怎么办 - AsEnumerable 对分页有什么影响?如果我说:
var page = model.Skip((page > 0 ? page - 1 : 0) * rows).Take(rows);
因为模型现在是 IEnumerable 而不是 IQueryable,所以当我们说 model.Skip().Take() 时,它是否必须先从数据库中加载整个数据集才能跳过和获取?(这会破坏分页的目的)
编辑:这个问题是笼统地写的 - 这些是具体细节:
我无法控制分页。我正在生成一个模型并将其传递给一个网格组件(在这种情况下为 DevExpress,但可以是任何网格)。发出分页命令的是网格组件。任何涉及在 AsEnumerable() 之前使用 .Skip().Take() 的解决方案在这里都是不可能的。
所以我需要能够将此模型传递给网格,同时确保模型使用延迟执行:
var model = _service.GetQuery
.Where(data => data.SomeFlag == true)
.Select(data => new {
data.Id,
data.Customer.Code,
data.Customer.Name,
// etc, select a few other properties
Foo = CalculateFoo(data.Bar);
});
所以现在我有一个摇滚与硬地的问题:
- 如果我将该模型传递给网格,它会在显示当前页面时抛出异常,因为 linq to sql 无法执行 CalculateFoo()
- 如果我添加 AsEnumerable() 那么网格可以显示当前页面,但它必须加载整个数据集才能这样做(加载数千行只是为了显示其中的 200 行)
- 如果我将 Foo 列排除在模型之外,那么我们将再次推迟执行,但网格缺少一列