La paginación y Entity Framework

0

Pregunta

En mi aplicación móvil, trato de recuperar datos de una tabla de mi base de datos SQL Server. Estoy usando EF y trato de usar la paginación para un mejor rendimiento. Necesito recuperar los datos desde el último elemento de la tabla. así que si la tabla tiene 20 filas, que yo, por la página 0, Id 20, 19, 18, 17, 16, a continuación, para página 1 de Identificadores de 15, 14, 13, 12, 11 y así sucesivamente...

El problema es este: lo que si, mientras que el usuario de "a" es la descarga de los datos de la tabla, el usuario "B" añadir fila? Si el usuario "Una" Página 0 (IDs 20, 19, 18, 17, 16), el usuario "B" en el mismo momento en añadir fila (por lo tanto, ID 21), con el clásico de la consulta, el usuario "A" de la página 1 tendrá IDs 16, 15, 14, 13, 12... así que otra vez ID 16

Mi código es muy simple:

int RecordsForPagination = 5; 
var list = _context.NameTable
                   .Where(my_condition)
                   .OrderByDescending(my_condition_for ordering)
                   .Skip (RecordsForPagination * Page)
                   .Take (RecordsForPagination)
                   .ToList();

Por supuesto Page es de tipo int que vienen desde el frontend.

¿Cómo puedo solucionar el problema?

He encontrado una solución, pero no sé si es el perfecto. Yo podría usar

.SkipWhile(x => x.ID >= LastID) 

en su lugar

.Skip (RecordsForPagination * Page)

y, por supuesto, LastID siempre se envía desde el frontend.

¿Cree usted que el rendimiento es siempre bueno con este código? Hay una solución mejor?

entity-framework linq sql-server
2021-11-22 23:06:34
1

Mejor respuesta

1

El impacto en el rendimiento dependerá en gran medida de su SQL Índice de aplicación y la cláusula order by. Pero no es tanto una cuestión sobre el rendimiento ya que se trata de obtener los resultados esperados.

Desbordamiento de la pila es un gran ejemplo donde hay un volumen de actividad de tal manera que cuando llegue al final de la página, la siguiente página puede contener registros de la página que acaba de ver debido a que el conjunto de registros subyacente ha cambiado (más puestos han sido añadidos)

Menciono esto porque en un sistema vivo es generalmente aceptados y, en algunos casos, de una espera de comportamiento. Como desarrolladores podemos apreciar el agregado de los gastos generales de tratar de mantener un único conjunto de resultados y reconocer que es mucho más bajo valor en el intento de evitar lo que parece duplicaciones como recorrer las páginas.

A menudo es suficiente para explicar por qué ocurre esto, en muchos casos se va a aceptar

Si es importante para usted para mantener el lugar en el original conjunto de resultados, entonces usted debe restringir la consulta con un Where la cláusula, pero usted necesita para recuperar el Id o la marca de tiempo en la consulta original. En el caso de que usted está tratando de usar LastIDpero para obtener el ultimo ID requeriría una consulta independiente en su propio porque la cláusula orderby le afectan.

Realmente no se puede utilizar .SkipWhile(x => x.ID >= LastID) para esto, porque skip es un proceso secuencial que se ve afectado por la orden, y se dis-que participan de la primera instancia que la expresión se evalúa a falseasí que si su orden no se basa en Id, su saltar mientras podrían ser el resultado es la omisión no hay registros en todo.

int RecordsForPagination = 5; 
int? MaxId = null;
...
var query = _context.NameTable.Where(my_condition);
// We need the Id to constraint the original search
if (!MaxId.HasValue)
    MaxId = query.Max(x => x.ID);

var list = query.Where(x => x.ID <= MaxId)
                .OrderByDescending(my_condition_for ordering)
                .Skip(RecordsForPagination * Page)
                .Take(RecordsForPagination);
                .ToList();

Es generalmente más simple para filtrar por un punto en el tiempo ya que este es conocido por el cliente sin necesidad de un viaje de ida a la DB, pero dependiendo de la implementación del filtrado en las fechas puede ser menos eficiente.

2021-11-22 23:55:04

Mi intención no fue la de recuperar LastID DB (porque, como usted dijo, este se vería afectado por Db en sí). mi intención era esta: - Interfaz de recuperar la Página 0 y el resultado son los Identificadores de 20, 19, 18, 17, 16 - Frontend recuperar la Página 1 y pasar a backend dos param: Página 1 y LastID de la Página anterior (en este caso LastID = 16) -> por lo que el resultado será IDs 15, 14, 13, 12, 11... y así sucesivamente. mi inglés no es perfecto... estamos diciendo la misma cosa?
user1106897

@user1106897 La técnica Chris se refiere a se llama conjunto de claves de Paginación, y por lo general es mucho mejor que la paginación por filas, que es de lo que se habla
Charlieface

Mucho es también una cuestión de rendimiento: paginación por filas es altamente ineficiente como todas las filas anteriores necesitan ser leídos en cada momento. Mientras que la paginación por clave (o el tiempo en este caso) es muy eficiente si hay un índice de apoyo
Charlieface

Charlie se enfrentan muchas gracias por el enlace, muy apreciada. Voy a tratar de usar los consejos
user1106897

Gracias @Charlieface el desempeño observación fue más supuestamente "olvidar el rendimiento, SkipWhile(id) no va a resolver el problema si desea cambiar el orden de la" Gran vínculo demasiado!
Chris Schaller

En otros idiomas

Esta página está en otros idiomas

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Slovenský
..................................................................................................................