c# - La inicialización de Entity Framework es LENTA: ¿qué puedo hacer para arrancarlo más rápido?
performance entity-framework-4 (3)
Aquí hay otra manera de hacerlo. Requiere un poco de trabajo manual, pero en realidad puede ser más adecuado para su escenario en el que le gustaría usar MsBuild. En lugar de crear vistas con Power Tools (lamento que no funcionen para usted), puede crearlas manualmente. Estos son los pasos:
- Primero necesita obtener artefactos para su contexto. Necesita todos los archivos csdl, ssdl y msl. Puede usar Edmwriter para obtenerlos. Tenga en cuenta que EdmxWriter devuelve un archivo edmx que combina los tres archivos por lo que debe dividirlos. Aquí está el código para este paso (tenga en cuenta que los espacios de nombres son específicos de EF4, si está pensando en utilizar EF5 y .NET Framework 4.5, deberá cambiarlos en consecuencia o seleccionar elementos solo por nombre local y no por nombre completo):
var ms = new MemoryStream();
using (var writer = XmlWriter.Create(ms))
{
EdmxWriter.WriteEdmx(new Context(), writer);
}
ms.Position = 0;
var xDoc = XDocument.Load(ms);
var ssdl = xDoc.Descendants("{http://schemas.microsoft.com/ado/2009/02/edm/ssdl}Schema").Single();
var csdl = xDoc.Descendants("{http://schemas.microsoft.com/ado/2008/09/edm}Schema").Single();
var msl = xDoc.Descendants("{http://schemas.microsoft.com/ado/2008/09/mapping/cs}Mapping").Single();
ssdl.Save("Context.ssdl");
csdl.Save("Context.csdl");
msl.Save("Context.msl");
- Cuando tienes artefactos puedes generar vistas usando la herramienta EdmGen. Como aquí lo hacemos manualmente, debe hacerlo desde el símbolo del sistema de VS. Aquí está el comando que usa para generar vistas:
EdmGen /mode:ViewGeneration /incsdl:Context.csdl /inmsl:Context.msl /inssdl:Context.ssdl /outviews:Context.Views.cs
- Agregue el archivo generado a su proyecto.
Si desea integrar la generación de vistas con su sistema de compilación, hay una opción más interesante: utilizar una plantilla T4. La plantilla se encargaría de los pasos anteriores. Puede encontrar más detalles sobre este enfoque aquí http://blogs.msdn.com/b/adonet/archive/2008/06/20/how-to-use-a-t4-template-for-view-generation.aspx . El único problema es que el ejemplo no es para el enfoque CodeFirst, por lo que debe cambiarse un poco, lo que no debería ser difícil.
De hecho, creé plantillas T4 para Code First. Puede encontrar un enlace para descargar en mi blog: http://blog.3d-logic.com/2012/05/28/entity-framework-code-first-and-pre-generated-views/
Las plantillas ahora están disponibles en Visual Studio Code Gallery. Aquí está el enlace a la publicación con todos los detalles: http://blog.3d-logic.com/2012/06/13/entity-framework-codefirst-view-generation-templates-on-visual-studio-code-gallery/
Mi modelo EF 4.3.1 tiene 200 tablas impares. El arranque inicial es horrible, varios minutos. Un perfil capturado por DotTrace implica algunas opciones terribles de algoritmo / escalabilidad en el marco, como lo demuestran los millones de llamadas a una cantidad de métodos y 36 millones de llamadas a IEnumerable.Contains (). Aquí hay un fragmento, todo esto se desencadena con la primera consulta realizada en la base de datos (las consultas futuras no hacen esto y están bien).
¿Qué puedo hacer con mi modelo para que esto sea menos doloroso? ¿Puedo precompilar esto de alguna manera? Mejor, ¿puede el equipo EF abordar estos problemas o abrir el marco para que yo pueda? ¿O al menos corregir la ortografía de Warapper
? :)
EDITAR: Una llamada EF específica que desencadena esto es básicamente var db = new MyDbContext(); db.Personnel.Where(a => a.Login == login).SingleOrDefault();
var db = new MyDbContext(); db.Personnel.Where(a => a.Login == login).SingleOrDefault();
. También un EF Migrations Seed () AddOrUpdate genera efectivamente la misma pila. El rastro más completo de la pila, que puede dar un poco más de contexto, está aquí: Fuller Stack Trace
EDITAR: Algunos enlaces relevantes:
- MSDN: Consideraciones de rendimiento (Entity Framework) (gracias a @AakashM)
- MSDN: EF Power Tools
- SO: Entity Framework 4.1 para un gran número de tablas (715)
EDIT2: Ahora que abren el código, parece que esta línea:
//Filter the 1:1 foreign key associations to the ones relating the sets used in these cell wrappers.
oneToOneForeignKeyAssociationsForThisWrapper =
oneToOneForeignKeyAssociationsForThisWrapper.Where(
it => (it.AssociationEndMembers.All(endMember => entityTypes.Contains(endMember.GetEntityType()))));
es el que necesita algo de trabajo. Está utilizando un algoritmo O (n ^ 2) cuando probablemente no sea necesario, pero no he mirado de cerca aún.
EDIT3: Felizmente, parece que el trabajo en EF6 está arreglando este código: http://entityframework.codeplex.com/discussions/396130
En la generación de vista pre EF6 se sabe que es lento para modelos más grandes. Por ahora, la solución es usar vistas pregeneradas. De esta manera, genera vistas en tiempo de diseño y evita este trabajo en tiempo de ejecución. Para hacerlo, descargue las herramientas de poder de EF y seleccione "Optimizar el modelo de datos de la entidad". Agregará un archivo C # a su proyecto que contiene vistas. El inconveniente es que tendrá que hacerlo cada vez que su modelo cambie. Nota: para generar vistas con la herramienta, llevará la misma cantidad de tiempo que lleva generar vistas en tiempo de ejecución (por lo que a veces debe tener paciencia). Aquí hay una publicación sobre EF Power Tools que podría ser útil: http://blogs.msdn.com/b/adonet/archive/2011/05/18/ef-power-tools-ctp1-released.aspx
Editar
Recientemente, creé una solución diferente que es mucho más cómoda de usar (tenga en cuenta que solo funciona en EF6) - http://blog.3d-logic.com/2013/12/14/using-pre-generated-views-without-having-to-pre-generate-views-ef6/
La generación de vistas es bastante rápida en la versión actual de Entity Framework. (6.1) Hay otra solución de almacenamiento en caché más amplia en preparación: https://entityframework.codeplex.com/workitem/1876 . Puedes esperar a que se acepte este parche o, si eres lo suficientemente valiente, puedes aplicarlo por ti mismo.