首页 > 解决方案 > Take() 使用实体框架获取表中的所有行(查询视图时)

问题描述

我得到以下行为:我有一个包含一些杂乱和遗留代码的视图,我想获得这个视图的分页结果。

通常,使用以下代码可以工作:

var itens = dbContext.Item.OrderBy(x => x.Id)
            .Skip((pageNumber - 1) * pageSize)
            .Take(pageSize)
            .ToList();

但是 EF 生成这个 SQL:

SELECT 
    [Extent1].[Id] AS [Id], 
    [Extent1].[Code] AS [Code], 
    [Extent1].[SubGroupCode] AS [SubGroupCode]
FROM 
    (SELECT 
         [Item].[Id] AS [Id], 
         [Item].[Code] AS [Code], 
         [Item].[SubGroupCode] AS [SubGroupCode]
     FROM 
         [dbo].[Item] AS [Item]) AS [Extent1]
ORDER BY 
    row_number() OVER (ORDER BY [Extent1].[Id] ASC)
    OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY 

这似乎返回了所有行,然后获得了 20 个所需的行。

执行以下 SQL 同时返回所有记录 (47s)

Select * Item

设置 TOP 20 会使查询立即运行。

我无法改变观点,但我认为这是不必要的。

我正在考虑一个更好的解决方案,而不仅仅是运行原始 SQL 或创建一个过程来返回值......

提前致谢。

编辑:

我做了一些改变和测试。他们没有解决我的问题,但我认为这将有助于理解它。

使用 lambda 值作为参数,代码如下所示:

var itens = dbContext.Item.OrderBy(x => x.Id)
                    .Take(() => pageSize)
                    .Skip(() => pageQty);

我得到了这个 SQL:

SELECT 
    [Limit1].[Id] AS [Id], 
    [Limit1].[Code] AS [Code]
FROM ( 
    SELECT TOP (@p__linq__0) 
    [Extent1].[Id] AS [Id], 
    [Extent1].[Code] AS [Code]
    FROM (
        SELECT 
        [Item].[Id] AS [Id], 
        [Item].[Code] AS [Code]
        FROM [dbo].[Item] AS [Item]) AS [Extent1]
        ORDER BY [Extent1].[Id] ASC
    )  AS [Limit1]
ORDER BY row_number() OVER (ORDER BY [Limit1].[Id] ASC)
OFFSET @p__linq__1 ROWS 

性能问题仍然存在,但如果在第一级使用 TOP 语句运行 SQL,我会立即得到响应。SQL:

DECLARE @p__linq__0 INT = 20
DECLARE @p__linq__1 INT = 0

SELECT 
    [Limit1].[Id] AS [Id], 
    [Limit1].[Code] AS [Code]
FROM ( 
    SELECT TOP (@p__linq__0) 
    [Extent1].[Id] AS [Id], 
    [Extent1].[Code] AS [Code]
    FROM (
        SELECT **TOP (@p__linq__0)**  
        [Item].[Id] AS [Id], 
        [Item].[Code] AS [Code]
        FROM [dbo].[Item] AS [Item]) AS [Extent1]
        ORDER BY [Extent1].[Id] ASC
    )  AS [Limit1]
ORDER BY row_number() OVER (ORDER BY [Limit1].[Id] ASC)
OFFSET @p__linq__1 ROWS 

标签: sql.netperformanceentity-frameworkview

解决方案


我想到了。

最后,我的观点有一个 DISTINCT 声明,这导致了性能问题。

奇怪的是,当我使用 TOP 20 语句时,它运行良好。

但是删除 DISTINCT 解决了这个问题。

谢谢!


推荐阅读