在代码中调用SKIP()或在函数中使用TOP

时间:2018-01-16 08:55:45

标签: c# sql-server entity-framework tsql entity-framework-6

我正在使用Entity Framework编写应用程序,其中我非常依赖用户定义的函数。

我对如何限制和分页结果集的最佳方式(最佳方式)有疑问。基本上我想知道这两个选项是否相同,或者一个是性能优先。

选项1。

//C#
var result1 = _DB.fn_GetData().OrderBy(x => Id).Skip(page *100).Take(100).ToList();

// SQL in fn_GetData
SELECT * FROM [Data].[Table]

选项2。

//C#
var result2 = _DB.fn_GetData(page = 0, size = 100).ToList();

// SQL in fn_GetData
SELECT * FROM [Data].[Table]
ORDER BY Id
OFFSET (size * page) ROWS FETCH NEXT size ROWS ONLY

对我而言,这些似乎产生了大致相同的结果,但也许我错过了一些关键方面。

3 个答案:

答案 0 :(得分:1)

当您的LINQ语句为AsEnumerableAsQueryable时,您必须知道。只要您的语句是IQueryable<...>,软件就会尝试将其转换为SQL并让数据库执行查询。一旦它真的丢失了IQueryable,并且已成为IEnumerable的实现,数据已被带到本地内存,所有进一步的LINQ语句将由您的进程执行,而不是由数据库执行

如果您使用调试器,您将看到fn_getData的返回值返回IEnumerable。这意味着fn_GetData的结果将被带到本地内存,而OrderBy等则由您的进程执行。

通常,仅将您将使用的记录移动到本地内存会更有效。此外:不要获取完整记录,而只获取您计划使用的属性。所以在这种情况下,我想你必须创建fn_GetData的扩展版本,只返回你计划使用的值

答案 1 :(得分:0)

我建议使用第二个选项,因为SQL Server可以比C#方法更快。

在第一个选项中,您可以获取表格中的所有记录并循环显示。但第二个选择,SQL Server为你做,你得到你想要的。

答案 2 :(得分:0)

您应该尽可能在数据库中应用limits和where子句(它取决于表索引)。第一个例子;

var result1 = _DB.fn_GetData().OrderBy(x => Id).Skip(page *100).Take(100).ToList();

// SQL in fn_GetData
SELECT * FROM [Data].[Table]

将整个表从数据库中检索到内存中,这会影响性能和可靠性。我强烈建议不要这么做。您应该考虑对数据库中的过滤记录进行一些限制。因此,在这种情况下,第二种选择是更好的方法。