2

我有一些数据库,现在它包含一个大约 100 行的表。但是将来它不会有 100 行而是 1 000 000+ 行,我必须小心我现在正在开发的 Web 应用程序。

下一个问题是:在网页上,我需要创建分页列表来向用户显示记录。这是我计划使用的代码示例

public IQueryable<MyTable> GetRows(int from, int to)
{
   var queryRes = (from row in SomeDataContext.MyTable
                   order by row.id
                   select row).AsQueriable();
   return queryRes.Take(to).Skip(from);
}

它只是代码示例。我没有运行它。但问题是在这种情况下会发生什么?我看到了两个场景

  1. 它将从数据库和服务器端加载所有行,并返回从“从”到“到”范围内的记录。其他将被忽略。在这种情况下,我的应用程序会有很大的麻烦。想象一下每次从数据库中加载 1 000 000 行。这将是灾难。
  2. 它将构造 SQL 请求,它将只返回我需要的行而不加载其他行。这正是我需要的。

我认为这将是 2 种情况,但我不确定也无法检查。我对么?

4

3 回答 3

4

作为旁注,您不必调用AsQueryable. 做就够了

var queryRes = SomeDataContext.MyTable.OrderBy(r => r.Id);
return queryRes.Take(to).Skip(from);

并回答您的问题 - 场景 2 将被执行。您始终可以使用 SQL Server Profiler 检查生成的 SQL,但如果您使用的是实体框架,您甚至可以执行queryRes.ToString(). queryRes.ToList()正如@Aron 正确指出的那样 - 只有在枚举结果(例如调用)时,才会对数据库实际执行查询。

这些问题更详细地解决了查找 SQL 代码的问题:

于 2013-04-12T07:28:49.923 回答
3

严格来说,1 和 2 都不正确。运行代码不会命中数据库。它构造了一个表达式树。调用代码仍然可以进一步修改表达式树,而无需访问数据库。

使用 IQueryable 接口不运行 SQL。正是在您调用IEnumerable.GetEnumerator()底层 Linq 提供程序时,将整个表达式转换为查询。本例是一个 SQL 查询,然后运行它。

例如,使用此代码。你可以有

void Main()
{
    var foo = from x in GetRows(10, 10)
            where x.Id > 1000
            select x;
    foreach(var f in foo)
    {
        //Stuff
    }
}

实际运行的sql实际上会更接近

SELECT a,b,c FROM 
(SELECT a,b,c, ROW_NUMBER() OVER (ORDER BY ...) as row_number
FROM Table
WHERE id > 1000) t0
WHERE to.row_number BETWEEN 10 and 20;

老实说,你做错了。您不需要 GetRows 方法。我会在构建表本身时直接调用 Linq 查询。您应该看看IRepositoryMVC 脚手架使用的模式。

最后,如果这意味着将其称为 AJAX 的 WebQuery,我将查看 .net 中的两个 OData 实现(WCF 数据服务和 WebAPI OData)。

于 2013-04-12T07:43:35.833 回答
1

你说的对。2.情景是会发生什么。当查询最终被执行时。

我建议扭转 Take - Skip,所以你从 Skip 开始

queryRes.Skip(from).Take(to)

Debuggen 这个方法不会对数据库进行任何调用。它只返回查询 - 而不是结果。

如果您想准确测试会发生什么,请尝试下载LinqPad - 它非常适合揭开 linq 查询的神秘面纱。

于 2013-04-12T07:30:10.920 回答