Pido disculpas por la falta de detalles en esta pregunta; lo primero que necesito ayuda es saber dónde buscar para obtener más detalles.C# Entity Framework 4 Propiedades de navegación que provocan un rendimiento lento en commit
tengo un problema con propiedades enity marco 4 de navegación aparentemente provocar pérdidas de rendimiento en la comisión de cambios:
this.ObjectContext.SaveChanges();
está tomando más de 30 segundos cuando una de las propiedades de navegación (tabla Receipts) contiene alrededor de 8000 filas (que no hay muchos, así que debería estar bien).
He utilizado el generador de perfiles de SQL y puedo ver que EF emite un SELECT * FROM recibos y que es muy lento:
exec sp_executesql N'SELECT
[Extent1].[Id] AS [Id],
// full field list cut for brevity
FROM [dbo].[Receipts] AS [Extent1]
WHERE [Extent1].[WarehouseId] = @EntityKeyValue1',
N'@EntityKeyValue1 int',@EntityKeyValue1=1
En el momento en que ni siquiera se puede ver por qué necesita seleccione todas las filas de esta tabla cuando se invoque ObjectContext.SaveChanges().
No necesita insertar 1 fila en esta tabla, pero eso no explica por qué selecciona primero todo y no explica por qué esa selección tarda tanto (la misma consulta toma < 1 segundo en consulta gerente)
Así que mi pregunta en este momento - no sé exactamente cuál es el problema todavía es - es:
- Dónde/cómo puedo buscar más información sobre el problema? No puedo depurar en ObjectContext.SaveChanges(), así que no sé qué está sucediendo dentro de él.
- ¿Por qué EF intentará seleccionar * de Recibos?
- ¿Por qué es tan lento? La misma consulta exacta copia + pega en gestor de consulta es casi instantáneo
EDIT:
he confirmado que es el código de recibo que es lento comentando la llamada a este método:
private void AddReceipt(PurchaseInvoice invoice,
PurchaseInvoiceLine invoiceLine)
{
if (invoice != null && invoiceLine != null)
{
Product product = invoiceLine.Product;
if (product != null)
{
Receipt receipt = new Receipt{ foo = bar };
WarehouseDetail detail = new WarehouseDetail{ foo = bar };
receipt.WarehouseDetails.Add(detail);
invoice.Receipts.Add(receipt);
}
}
}
Pero todavía no puedo ver por qué esto causa que EF emita esa consulta * seleccionada.
Creo que podría ser un problema de carga diferida causado por invoice.Receipts.Add(receipt)
. Porque antes de esa línea, la factura. Recibos está vacía, y para agregar. Agregar a los recibos, primero debe cargar la colección. PERO eso no explica por qué está seleccionando por warehouseId = 1, cuando debería seleccionarse por el invoiceId.
EDIT 2:
He "fija" el problema mediante la sustitución del código de EF en este método con comandos directos SQL. Esta no es una gran idea. No debería lanzar SQL cuando tengo un ORM perfectamente bueno. Pero en este momento todavía no entiendo por qué EF corría el selecto * consulta
private void AddReceipt(PurchaseInvoice invoice,
PurchaseInvoiceLine invoiceLine)
{
if (invoice != null && invoiceLine != null)
{
Product product = invoiceLine.Product;
if (product != null)
{
Receipt receipt = new Receipt{ foo = bar };
WarehouseDetail detail = new WarehouseDetail{ foo = bar };
int id = SqlHelper.AddWarehouseDetail(detail);
receipt.WarehouseDetailId = id;
SqlHelper.AddReceipt(receipt);
}
}
}
+1 por sugerir efprof.com - No era consciente de esto. -1 por el costo, $ 305? Wow –
Re a su punto n. ° 2. Intento encontrar la razón: probablemente es allí donde radica el problema. Encontré que la propiedad de navegación no se estaba utilizando correctamente, pero arreglar esto no ha eliminado la consulta * select –
He encontrado dónde sucede comentando cosas hasta que funcionó. Pero no puedo ver en el código por qué EF emite la consulta de selección. –