.net - sql pool connections




Entity Framework y Connection Pooling (3)

Recientemente comencé a usar Entity Framework 4.0 en mi aplicación .NET 4.0 y tengo curiosidad por algunas cosas relacionadas con la agrupación.

  1. La agrupación de conexiones que conozco está gestionada por el proveedor de datos ADO.NET, en mi caso, el del servidor MS SQL. ¿Se aplica esto cuando crea una instancia de un nuevo contexto de entidades ( ObjectContext ), es decir, el new MyDatabaseModelEntities() parámetros?

  2. ¿Cuáles son las ventajas y desventajas de a) crear un contexto global de entidades para la aplicación (es decir, una instancia estática) o b) crear y exponer un contexto de entidades para cada operación / método dado, con un bloque de using ?

  3. ¿Alguna otra recomendación, mejores prácticas o enfoques comunes para ciertos escenarios que debería conocer?


  1. La agrupación de conexiones se maneja como en cualquier otra aplicación ADO.NET. La conexión de entidad sigue utilizando la conexión tradicional de base de datos con la cadena de conexión tradicional. Creo que puede desactivar la agrupación de conexiones en la cadena de conexión si no desea usarla. (Lea más sobre la agrupación de conexiones de SQL Server (ADO.NET) )
  2. Nunca jamás uses el contexto global. ObjectContext implementa internamente varios patrones, incluido el Mapa de Identidad y la Unidad de Trabajo. El impacto del uso del contexto global es diferente según el tipo de aplicación.
  3. Para aplicaciones web use un solo contexto por solicitud. Para servicios web use un solo contexto por llamada. En WinForms o la aplicación WPF use un solo contexto por formulario o por presentador. Puede haber algunos requisitos especiales que no permitan utilizar este enfoque, pero en la mayoría de las situaciones esto es suficiente.

Si desea saber qué impacto tiene el contexto de un solo objeto para la aplicación WPF / WinForm, consulte este article . Se trata de NHibernate Session pero la idea es la misma.

Editar:

Cuando usa EF, por defecto, carga cada entidad solo una vez por contexto. La primera consulta crea una instancia de entidad y la almacena internamente. Cualquier consulta posterior que requiera una entidad con la misma clave devuelve esta instancia almacenada. Si los valores en el almacén de datos cambiaron, aún recibirá la entidad con los valores de la consulta inicial. Esto se llama patrón de mapa de identidad . Puede forzar que el contexto del objeto vuelva a cargar la entidad, pero volverá a cargar una sola instancia compartida.

Los cambios realizados en la entidad no se conservarán hasta que llame a SaveChanges en el contexto. Puedes hacer cambios en múltiples entidades y almacenarlas a la vez. Esto se llama patrón de unidad de trabajo . No puede decir de forma selectiva qué entidad vinculada modificada desea guardar.

Combina estos dos patrones y verás algunos efectos interesantes. Solo tienes una instancia de entidad para toda la aplicación. Cualquier cambio en la entidad afecta a toda la aplicación, incluso si los cambios aún no se mantienen (comprometidos). En la mayoría de las veces esto no es lo que quieres. Supongamos que tiene un formulario de edición en la aplicación WPF. Está trabajando con la entidad y decide cancelar la edición compleja (cambiar valores, agregar entidades relacionadas, eliminar otras entidades relacionadas, etc.). Pero la entidad ya está modificada en contexto compartido. ¿Qué harás? Sugerencia: no conozco ningún CancelChanges o UndoChanges en ObjectContext .

Creo que no tenemos que discutir el escenario del servidor. El simple hecho de compartir una sola entidad entre múltiples solicitudes HTTP o llamadas a servicios web hace que su aplicación sea inútil. Cualquier solicitud solo puede activar SaveChanges y guardar datos parciales de otra solicitud porque está compartiendo una sola unidad de trabajo entre todos ellos. Esto también tendrá otro problema: el contexto y cualquier manipulación con entidades en el contexto o una conexión de base de datos utilizada por el contexto no es segura para subprocesos.

Incluso para una aplicación de solo lectura, un contexto global no es una buena opción porque probablemente desee obtener datos nuevos cada vez que consulte la aplicación.


De acuerdo con la documentación de EF6 (4,5 también): https://msdn.microsoft.com/en-us/data/hh949853#9

9.3 Contexto por solicitud

Los contextos de Entity Framework están diseñados para ser utilizados como instancias de corta duración con el fin de proporcionar la experiencia de rendimiento más óptima . Se espera que los contextos sean de corta duración y se descarten, y como tal se han implementado para que sean muy ligeros y reutilicen los metadatos siempre que sea posible. En los escenarios web, es importante tener esto en cuenta y no tener un contexto por más de la duración de una sola solicitud. De manera similar, en escenarios que no sean de la web, el contexto debe descartarse en función de su comprensión de los diferentes niveles de almacenamiento en caché en el Entity Framework. En términos generales, se debe evitar tener una instancia de contexto a lo largo de la vida de la aplicación, así como los contextos por hilo y los contextos estáticos.


Según Daniel Simmons:

Cree una nueva instancia de ObjectContext en una declaración de uso para cada método de servicio para que se elimine antes de que el método regrese. Este paso es crítico para la escalabilidad de su servicio. Se asegura de que las conexiones de la base de datos no se mantengan abiertas en todas las llamadas de servicio y que el estado temporal utilizado por una operación en particular se recoja cuando se termina esa operación. Entity Framework guarda en caché automáticamente los metadatos y otra información que necesita en el dominio de la aplicación, y ADO.NET agrupa las conexiones de la base de datos, por lo que volver a crear el contexto cada vez es una operación rápida.

Esto es de su artículo completo aquí:

http://msdn.microsoft.com/en-us/magazine/ee335715.aspx

Creo que este consejo se extiende a las solicitudes HTTP, por lo que sería válido para ASP.NET. Una aplicación de cliente pesado, tal como una aplicación WPF podría ser el único caso para un contexto "compartido".







connection-pooling