Aumente el rendimiento en la consulta con muchas asignaciones de uno a muchos

dapper entity-framework petapoco sql-server

Pregunta

Estoy usando Entity Framework para SQL Azure y en una página de mi aplicación mostramos bastantes datos relacionados al usuario. Estamos cargando un máximo de 30 elementos en la página, pero cada elemento tiene 5 asignaciones de uno a muchos a otros objetos. El tiempo de consulta está en un nivel razonable, pero estoy obteniendo bastante rendimiento en el mapeo de objetos. (casi un segundo completo).

Aquí hay un ejemplo de cómo se ve mi objeto

public class Task
{
    public string Name {get; set;}
    public string Status {get; set;}
    public DateTime DueDate {get; set;}
    public IEnumerable<TaskData> Data {get; set;}
    public IEnumerable<Transaction> Transactions {get; set;}
    public IEnumerable<File> Files {get; set;}
    public IEnumerable<Comment> Comments {get; set;}
    public IEnumerable<People> People {get; set;}
}

Una tarea tiene un nombre, un estado y una fecha de vencimiento. También tiene muchos TaskData que son pares personalizados de nombre / valor, muchas transacciones que muestran un historial de la tarea, muchos archivos, muchos comentarios y muchas personas que trabajan en él.

Mi consulta EF se ve algo así.

var Items = context.Items.Include(x=>x.Data).Include(x=>x.Files).Include(x=>x.Comments).Include(x=>x.People).Where(some constraint).ToList();

La relevancia de una tarea específica se basa primero en el estado y luego en la fecha de vencimiento. Así que he creado una anulación de IComparable para usar con sort. El punto es que las consultas paginado no funcionan bien en este escenario porque el ordenamiento no se basa en una int o una fecha (¿estoy en lo cierto?)

En el resto de nuestra aplicación, mostramos menos información sobre cada tarea y Linq2Entities funciona bien. El mapeo de objetos en este caso nos está matando. He ido por el camino de ir directamente a la base de datos con Dapper, pero el mapeo de uno a muchos tiene sus salvedades. Para algunas relaciones, creo que funcionaría bien, pero no para 5-6. Mi siguiente aspecto fue PetaPoco, pero no llegué demasiado lejos antes de pensar que sería mejor que hiciera la pregunta aquí primero.

¿Estoy loco por intentar traer tantos datos? ¿Cuáles son mis opciones para obtener el máximo rendimiento de esto? Tomaré un poco de complejidad ya que es la única área de la aplicación.

Respuesta aceptada

Estoy dispuesto a apostar que tu consulta EF está retirando demasiados datos. La cuestión es que la técnica de recuperación "óptima" depende en gran medida del tipo y la cantidad de datos que se extraen.

Sabiendo que desde el principio le permite ajustar las consultas que se ejecutan en función de su conjunto de datos esperado.

Por ejemplo ... si solo está tirando de un número limitado de entidades con muchas subentidades, el patrón que escribí aquí funciona bien:

¿Cómo mapeo listas de objetos anidados con Dapper?

Si sabe qué ID está utilizando y hay menos de 2000, puede atajarlo todo al consultar una sola cuadrícula y mapear usando QueryMultiple por ejemplo:

cnn.QueryMultiple(@"select * from Tasks where Id in @ids 
select * from Files where TaskId in @ids
.. etc ..", new {ids = new int[] {1,2,3}});

Si está tirando de un conjunto más grande, es posible que deba realizar un lote, o hacerlo en fases.


Para su ejemplo particular, consultaría Tasks para obtener todos los identificadores de tareas y datos, luego correlacionaré las relaciones utilizando un único QueryMultiple para todas las tablas asociadas.



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué