Marco de entidades y agrupación de conexiones

Resuelto Noldorin asked hace 14 años • 4 respuestas

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

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

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

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

Noldorin avatar Sep 06 '10 23:09 Noldorin
Aceptado
  1. La agrupación de conexiones se maneja como en cualquier otra aplicación ADO.NET. La conexión de entidad todavía utiliza una conexión de base de datos tradicional con una cadena de conexión tradicional. Creo que puedes desactivar la agrupación de conexiones en la cadena de conexión si no quieres usarla. (lea más sobre la agrupación de conexiones de SQL Server (ADO.NET) )
  2. Nunca utilices el contexto global. ObjectContext implementa internamente varios patrones, incluidos Identity Map y Unit of Work. El impacto del uso del contexto global es diferente según el tipo de aplicación.
  3. Para aplicaciones web, utilice un contexto único por solicitud. Para servicios web, utilice un contexto único por llamada. En la aplicación WinForms o WPF, utilice un contexto único 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 objeto único para la aplicación WPF/WinForm, consulte este artículo . Se trata de NHibernate Session pero la idea es la misma.

Editar:

Cuando usa EF, de forma predeterminada 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 recargue la entidad, pero recargará una única instancia compartida.

Cualquier cambio realizado en la entidad no persiste hasta que se invoca SaveChangesel contexto. Puede realizar cambios en varias entidades y almacenarlas a la vez. Esto se llama patrón de Unidad de Trabajo . No puede decir de forma selectiva qué entidad adjunta modificada desea guardar.

Combina estos dos patrones y verás algunos efectos interesantes. Sólo tiene 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 persisten (se confirman). En la mayoría de los casos esto no es lo que quieres. Suponga que tiene un formulario de edición en la aplicación WPF. Estás trabajando con la entidad y decides cancelar la edición compleja (cambiar valores, agregar entidades relacionadas, eliminar otras entidades relacionadas, etc.). Pero la entidad ya está modificada en un contexto compartido. ¿Qué vas a hacer? Sugerencia: No conozco ningún CancelChanges o UndoChanges en ObjectContext.

Creo que no tenemos que discutir el escenario del servidor. Simplemente compartir una sola entidad entre múltiples solicitudes HTTP o llamadas a servicios web hace que su aplicación sea inútil. Cualquier solicitud puede simplemente activar SaveChangesy guardar datos parciales de otra solicitud porque está compartiendo una sola unidad de trabajo entre todas ellas. 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 datos nuevos cada vez que consulte la aplicación.

Ladislav Mrnka avatar Sep 06 '2010 17:09 Ladislav Mrnka

Según Daniel Simmons:

Cree una nueva instancia de ObjectContext en una declaración Usando para cada método de servicio para que se elimine antes de que regrese el método. Este paso es fundamental para la escalabilidad de su servicio. Garantiza que las conexiones de la base de datos no se mantengan abiertas durante las llamadas de servicio y que el estado temporal utilizado por una operación en particular se recolecte como basura cuando esa operación finalice. Entity Framework almacena automáticamente en caché 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 recrear 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 con estado, como una aplicación WPF, podría ser el único caso para un contexto "compartido".

Dave Swersky avatar Sep 06 '2010 16:09 Dave Swersky

El siguiente código ayudó a que mi objeto se actualizara con valores nuevos de la base de datos. El comando Entry(object).Reload() fuerza al objeto a recuperar los valores de la base de datos.

GM_MEMBERS member = DatabaseObjectContext.GM_MEMBERS.FirstOrDefault(p => p.Username == username && p.ApplicationName == this.ApplicationName);
DatabaseObjectContext.Entry(member).Reload();
HGMamaci avatar Mar 13 '2014 00:03 HGMamaci