Подтвердить что ты не робот

Пейджинг в инфраструктуре Entity

В Entity Framework, используя LINQ to Entities, подкачка базы данных обычно выполняется следующим образом:

int totalRecords = EntityContext.Context.UserSet.Count;
var list     = EntityContext.Context.UserSet
                 .Skip(startingRecordNumber)
                 .Take(pageSize)
                 .ToList();

Это приводит к вызовам базы данных TWO​​strong > .

Скажите, как уменьшить его до ОДНОГО вызова базы данных.

Спасибо.

4b9b3361

Ответ 1

Что не так с двумя вызовами? Это небольшие и быстрые запросы. Базы данных предназначены для поддержки множества небольших запросов.

Разработка сложного решения для выполнения одного запроса для поискового вызова не приведет к большой окупаемости.

Ответ 2

Использование Esql и сопоставление хранимой процедуры с сущностью могут решить проблему. SP будет возвращать totalRows в качестве выходного параметра и текущей страницы в качестве набора результатов.

CREATE PROCEDURE getPagedList(
@PageNumber int,
@PageSize int,
@totalRecordCount int OUTPUT
AS

//Return paged records

Просьба сообщить.

Спасибо.

Ответ 3

Hmmm... фактический вызов, который использует пейджинг, второй - это один вызов.

Второй вызов состоит в том, чтобы определить общее количество строк - это совсем другая операция, и я не знаю, каким образом вы могли бы объединить эти две отдельные операции в один вызов базы данных с помощью Entity Framework.

Вопрос: вам действительно нужно общее количество строк? Зачем? Это стоит второй вызов базы данных или нет?

Другой вариант, который у вас есть, - использовать EntityObjectSource (в ASP.NET), а затем привязать его, например. GridView и включить AllowPage и AllowSorting и т.д. в GridView и позволить среде выполнения ASP.NET обрабатывать всю важную работу по извлечению соответствующей страницы данных и ее отображению.

Марк

Ответ 4

ALTER proc [dbo].[GetNames]
    @lastRow bigint,
    @pageSize bigint,
    @totalRowCount bigint output
as
begin

select @totalRowCount = count(*) from _firstNames, _lastNames

select
    FirstName,
    LastName,
    RowNumber
from
(
    select
        fn.[FirstName] as FirstName,
        ln.[Name] as LastName,
        row_number() over( order by FirstName ) as RowNumber
    from
        _firstNames fn, _lastNames ln
) as data
where
    RowNumber between ( @lastRow + 1 ) and ( @lastRow + @pageSize )

end 

Невозможно получить это в один вызов, но это работает достаточно быстро.

Ответ 5

Эти запросы слишком малы для DBManager, и я не могу понять, почему вы хотите это сделать, так или иначе, чтобы уменьшить его до ONE, используйте это:

var list     = EntityContext.Context.UserSet
                 .Skip(startingRecordNumber)
                 .Take(pageSize)
                 .ToList();
int totalRecords = list.Count;

Ответ 6

Предположим, вы хотите получить детали страницы с размером страницы = 4

int page =2;
int pagesize=4;

var pagedDetails= Categories.Skip(pagesize*(page-1)).Take(pagesize)
.Join(Categories.Select(item=>new {item.CategoryID,Total = Categories.Count()}),x=>x.CategoryID,y=>y.CategoryID,(x,y)=>new {Category = x,TotalRows=y.Total});

Выход будет содержать все сведения о категориях и итогах.

Один вызов БД.

Сгенерированный SQL

-- Region Parameters
DECLARE @p0 Int = 2
DECLARE @p1 Int = 4
-- EndRegion
SELECT [t2].[CategoryID], [t2].[CategoryName], [t2].[Description], [t2].[Picture], [t5].[value] AS [TotalRows]
FROM (
    SELECT [t1].[CategoryID], [t1].[CategoryName], [t1].[Description], [t1].[Picture], [t1].[ROW_NUMBER]
    FROM (
        SELECT ROW_NUMBER() OVER (ORDER BY [t0].[CategoryID], [t0].[CategoryName]) AS [ROW_NUMBER], [t0].[CategoryID], [t0].[CategoryName], [t0].[Description], [t0].[Picture]
        FROM [Categories] AS [t0]
        ) AS [t1]
    WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p0 + @p1
    ) AS [t2]
INNER JOIN (
    SELECT [t3].[CategoryID], (
        SELECT COUNT(*)
        FROM [Categories] AS [t4]
        ) AS [value]
    FROM [Categories] AS [t3]
    ) AS [t5] ON [t2].[CategoryID] = [t5].[CategoryID]
ORDER BY [t2].[ROW_NUMBER]