entity-framework - entity framework cargar objetos relacionados
Entity Framework carga la colección de elementos secundarios con un orden de clasificación (2)
Tengo dos tablas, una principal y una secundaria. La tabla secundaria tiene una clasificación de columnas (un valor numérico). Debido al soporte faltante de EF para persistir un IList incluido el orden de clasificación sin exponer el sortorder (consulte el orden de clasificación de colección hijo persistente de Entity Framework ) mi clase secundaria también tiene una propiedad SortOrder, de modo que puedo almacenar los elementos secundarios con el género orden.
A diferencia del autor de la pregunta de referencia, intento cargar los niños siempre ordenados. Entonces, si cargo una instancia principal, espero que la colección hija esté ordenada por orden de clasificación. ¿Cómo puedo lograr este comportamiento con Code First Fluent API y POCO''s?
Sugerencia: no es una opción para llamar .Sort (...) en la colección de elementos secundarios.
No puede lograrlo directamente porque ni la carga ansiosa o diferida en EF admite ordenar o filtrar.
Tus opciones son:
- Ordene los datos en su aplicación después de cargarlos desde la base de datos
- Ejecute una consulta separada para cargar registros secundarios. Una vez que use la consulta por separado, puede usar
OrderBy
La segunda opción se puede usar con carga explícita:
var parent = context.Parents.First(...);
var entry = context.Entry(parent);
entry.Collection(e => e.Children)
.Query()
.OrderBy(c => c.SortOrder)
.Load();
Puede hacer esto de manera eficiente en una sola consulta, la gramática es simplemente incómoda:
var groups = await db.Parents
.Where(p => p.Id == id)
.Select(p => new
{
P = p,
C = p.Children.OrderBy(c => c.SortIndex)
})
.ToArrayAsync();
// Query/db interaction is over, now grab what we wanted from what was fetched
var model = groups
.Select(g => g.P)
.FirstOrDefault();
Explicación
nota asincrónica
Por casualidad async
extensiones async
aquí, que probablemente debería usar, pero puede deshacerse de await
/ async
si necesita una consulta sincrónica sin dañar la clasificación eficiente de los elementos secundarios.
Primer pedazo
Por defecto, todos los objetos EF captados desde el Db son "rastreados". Además, el equivalente de EF a SQL Select
está diseñado en torno a Objetos anónimos, que nos vemos seleccionando en la parte superior. Cuando se crea el Objeto Anónimo, los objetos asignados a P
y C
son rastreados, lo que significa que sus relaciones son anotadas y su estado es mantenido por EF Change Tracker. Como C
es una lista de niños en P
, aunque no solicitó que se relacionen explícitamente en su Objeto anónimo, EF los carga de todos modos como esta colección secundaria, debido a la relación que ve en el esquema.
Para obtener más información, puede dividir lo anterior en dos consultas separadas, cargando solo el objeto principal, y luego solo la lista secundaria, en llamadas Db completamente diferentes. El EF Change Tracker notará y cargará los niños en el objeto principal por usted.
Segundo trozo
Hemos engañado a EF para que devuelva los niños ordenados. Ahora tomamos solo el objeto Parent - sus hijos seguirán unidos en el orden que deseábamos.
Nulos y tablas como conjuntos
Aquí hay un incómodo 2-paso principalmente para las mejores prácticas en torno a los nulos; está ahí para hacer 2 cosas:
Piense en cosas en el DB como conjuntos hasta el último momento absoluto posible.
Evitar excepciones nulas.
En otras palabras, el último trozo podría haber sido:
var model = groups.First().P;
Pero si el objeto no estaba presente en el DB, eso explotará con una excepción de referencia nula. C # 6 presentará otra alternativa, el operador de coalescencia de propiedad nula , por lo que en el futuro podría reemplazar el último bloque con:
var model = groups.FirstOrDefault()?.P;