Si estás trabajando en ASP.NET y LINQ2SQL o ADO.NET EF, te habrás preguntado cual es la mejor estrategia o solución para manejar el DataContext o el ObjectContext. Intentaré responder esta pregunta planteando varias alternativas que he conocido, pero verás que cada una tiene sus ventajas y desventajas, y la elección dependerá del escenario donde necesites aplicarlo.
Por cuestiones de simplicidad, a continuación hago referencia al ObjectContext de ADO.NET EF, pero la problemática es la misma con el DataContext de LINQ to SQL.
1. Un contexto por Session
A más de uno se le habrá ocurrido implementar alguna especie de Singleton y almacenar el ObjectContext en el objeto Session de ASP.NET.
Ventajas
- Existe un único contexto para toda la sesión del usuario
- Todas las operaciones se realizan usando ese único contexto por usuario.
- No deberían aparecer los problemas de que no se puede actualizar una entidad porque está asociada a otro contexto.
Desventajas
- Las opciones como ObjectTrackingEnabled o DeferredLoadingEnabled se aplicarían para todas las operaciones.
- El contexto puede crecer mucho y afectar la escalabilidad de la aplicación.
2. Un contexto por Request
La idea aquí es similar a la anterior, pero en lugar de almacenar el contexto en el objeto Session, lo guardamos en la colección HttpContext.Items. Esta colección se crea para cada Request y solo existe durante la ejecución de la solicitud.
Ventajas
- El contexto solo vive durante el hilo de ejecución de cada Request.
- Las operaciones de diferentes clases de acceso a datos pueden compartir el mismo contexto.
- La escalabilidad de la aplicación no debería verse afectada, pues el contexto se destruye al finalizar el Request.
Desventajas
- Las opciones como ObjectTrackingEnabled o DeferredLoadingEnabled siguen afectando a todas las operaciones.
- Existe una sobrecarga de crear el contexto con cada Request. Aunque esa sobrecarga suele ser despreciable.
3. Un contexto por instancia de acceso a datos
En lugar de guardar el contexto en la sesión o en el Thread del Request, lo creamos al instanciar la clase de acceso a datos. Por ejemplo, en el método constructor de la clase.
Ventajas
- El contexto tiene el mismo ciclo de vida que la clase de acceso datos.
- Las operaciones de la misma clase de acceso a datos pueden compartir el contexto.
- La escalabilidad de la aplicación no debería verse afectada, el contexto se destruye cuando se destruye la clase.
Desventajas
- Las opciones como ObjectTrackingEnabled o DeferredLoadingEnabled siguen afectando a todas las operaciones en la misma clase.
- Otras clases de acceso a datos no pueden compartir el mismo contexto.
- Existe una sobrecarga de crear el contexto con cada instancia. Esta sobrecarga puede afectar la performance si muchas instancias de acceso a datos se crean con cada request.
4. Un contexto por operación de acceso a datos
Esta sería la forma más atómica de manejar el contexto. Cada operación de acceso a datos crea el contexto, lo usa y lo libera.
Ventajas
- El contexto tiene un ciclo de vida mínimo.
- La escalabilidad de la aplicación no debería verse afectada, el contexto se destruye cuando finaliza el método.
- Las opciones como ObjectTrackingEnabled o DeferredLoadingEnabled solo afectan a todas las operaciones encerradas por el método.
Desventajas
- Otros métodos o clases de acceso a datos no pueden compartir el mismo contexto.
Estoy seguro que podemos encontrar otras alternativas o variantes. Aunque no he encontrado ninguna 100% beneficiosa.
De todas las variantes enumeradas aquí, en mis proyectos suelo utilizar la variante 2 (Un contexto por request) o la 3 (Un contexto por instancia de acceso a datos). Y hasta el momento no he tenido problemas significativos.
Si tienes una estrategia mejor o más recomendable para manejar el contexto de datos de LINQ2SQL o ADO.NET EF, no dudes en compartirla.
En un futuro post, intentaré poner algunos ejemplos de código sobre cómo gestiono el contexto de datos en mis proyectos.
Espero que sirva.
Saludos, Gus