我正在使用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
对我而言,这些似乎产生了大致相同的结果,但也许我错过了一些关键方面。
答案 0 :(得分:1)
当您的LINQ语句为AsEnumerable
且AsQueryable
时,您必须知道。只要您的语句是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]
将整个表从数据库中检索到内存中,这会影响性能和可靠性。我强烈建议不要这么做。您应该考虑对数据库中的过滤记录进行一些限制。因此,在这种情况下,第二种选择是更好的方法。