我有一些数据库,现在它包含一个大约有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);
}
这只是代码示例。我没有运行它。 但问题是在这种情况下会发生什么?我看到两个场景
我认为这将是两个场景,但我不确定,也无法检查。我是对的吗?
答案 0 :(得分:4)
作为旁注,您不必致电AsQueryable
。这就足够了
var queryRes = SomeDataContext.MyTable.OrderBy(r => r.Id);
return queryRes.Take(to).Skip(from);
要回答你的问题 - 方案2将被执行。您始终可以使用SQL Server Profiler检查生成的SQL,但是如果您使用的是Entity Framework,您甚至可以queryRes.ToString()
。正如@Aron正确指出的那样 - 只有在枚举结果时才会对数据库执行查询(例如,调用queryRes.ToList()
)。
这些问题解决了更详细地查找SQL代码的问题:
答案 1 :(得分:3)
严格来说,1和2都不正确。运行代码不会命中数据库。它构造了一个表达式树。调用代码仍然可以进一步修改表达式树而无需访问数据库。
使用IQueryable接口,不运行SQL。正是在您调用IEnumerable.GetEnumerator()
时,底层Linq Provider将WHOLE表达式转换为查询。在这种情况下是一个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查询。您应该看一下MVC脚手架使用的IRepository
模式。
最后,如果要将其称为AJAX的WebQuery,我将查看.net中的两个OData实现(WCF数据服务和WebAPI OData)。
答案 2 :(得分:1)
你是对的。 2.场景将会发生。当查询是eventuallty exectuted时。
我建议反转Take - Skip,所以你从Skip开始
queryRes.Skip(from).Take(to)
Debuggen此方法不会对数据库进行任何调用。它只返回查询 - 而不是resualt。
如果您想要准确测试会发生什么,请尝试下载LinqPad - 这对于解密linq查询非常有用。