30

MVC 3 + EF 4.1¿Cuál es la mejor manera de crear instancias y eliminar DbContext en MVC?

estoy eligiendo entre dos enfoques para hacer frente a DbContext:

  1. Instantiate en Application_BeginRequest, ponerlo en HttpContext.Current.Items y disponer en Application_EndRequest.
  2. Crear desechable UnitOfWork (envoltorio tipode para DbContext) y empezar cada acción del controlador con using(var unitOfWork = new UnitOfWork()) { ... }

Comparte tu experiencia por favor: ¿Cuál prefiere? ¿Cuáles son los pros y los contras de cada enfoque?

+0

Usar el enfoque de bloques tiene algunas desventajas. Causa muchos viajes redondos a la base de datos y uso indebido de transacciones en el marco de la Entidad. consulte http://ayende.com/blog/4775/new-profiler-feature-avoid-writes-from-multiple-sessions-in-the-same-request – marvelTracker

+0

¿Por qué causa más viajes de ida y vuelta?Se supone que una solicitud http debe ejecutar una acción en la mayoría de los casos, por lo que si ajusta el código de la acción completa en este bloque de uso, no habría más solicitudes de base de datos en comparación con la primera aproximación. La otra cosa con el enfoque 'por acción' es que siempre debe tener en cuenta un ámbito en el que se puede invocar la base de datos y colocar el bloque de manera apropiada. Por ejemplo, si su modelo contiene alguna colección para ser cargada de forma diferida en una representación de Vista de tiempo, la declaración que devuelve Vista (Modelo) debe estar dentro del bloque. – YMC

+0

Si usa DbContext en la envoltura de la capa de controlador con UnitOfWork crea una fuerte dependencia en la capa de interfaz de usuario y su enfoque de base de datos. Entonces necesitas una capa de servicio y una capa de repositorio. Después de eso, si tus repositorios tienen UnitOfWork por separado con el uso de bloques, eso será un problema. porque todos y cada uno de los repositorios crean transacciones y viajes innecesarios de ida y vuelta a la base de datos. Ver el enlace de arriba para más detalles. Si está seguro acerca de una llamada de servicio por solicitud, entonces puede usar la unidad de trabajo dentro del método de servicio. Sin embargo, no es garantía. – marvelTracker

Respuesta

18

que sugeriría que utiliza un marco de inyección de dependencias. Puede registrar su DbContext como por solicitud

container.RegisterType<MyDbContext>().InstancePerHttpRequest(); 

e inyectarlo como un parámetro de constructor para el controlador.

public class MyController : Controller 
{ 
    public MyController(MyDbContext myDbContext) 
    { 
     _myDbContext = myDbContext; 
    } 
} 

Si el tipo registrada implementa IDisposable continuación, el marco DI dispondrá que cuando la solicitud termina.

1er enfoque: es mucho más limpio utilizar el marco de ID que implementarlo manualmente. Además, todas sus solicitudes pueden no necesitar su UoW.

Segundo enfoque: El controlador no debe saber cómo construir su UoW (DbContext). El propósito no es reducir el acoplamiento entre los componentes.

+0

Correcto, es mejor usar el contenedor de IoC que manejar BeginRequset y EndRequest, pero todavía me parece bastante cercano al número 1, es por eso que ni siquiera lo he extraído como un enfoque separado. Lo que es más importante para mí es comparar 2 formas de acceder y controlar el ciclo de vida de DbContext (= Unidad de trabajo): la primera implica que la infraestructura ASP.NET/IoC es responsable de ella, la segunda es acerca de cada acción de controlador en cargar. – YMC

+0

@YMC Respuesta editada. Su segundo enfoque introducirá el acoplamiento entre su controlador y la implementación de UoW. Te sugiero que lo evites. – Eranga

+3

Introducir la capa de servicio e inyectar servicios al controlador. El servicio puede tener muchos repositorios y los repositorios dependen de la envoltura de UnitOfWork con EFDbContext. Luego use DI para inyectar esas dependencias. Luego, puede obtener la ventaja de Separation of Concerns. – marvelTracker

-1
+2

El OP no dijo nada sobre poner el DbContext en un campo estático ... quiere ponerlo en HttpContext.Current.Items, que es perfectamente seguro por lo que puedo ver –

+0

No dije que puse DbContext en global.asax . Dije que puse el código que instancia y elimina DbContext. DbContext está en HttpContext.Current.Items. Es seguro para subprocesos. – YMC

2

Actualmente utilizamos repositorios inyectados con UoW (unidad de trabajo) instanciados a través del localizador de servicios de una fábrica de repositorios. Unity controla la vida de esta manera quitándole el trabajo.

Su aplicación particular variará dependiendo de si el uso de POCO de entidad objetos, etc ..

última instancia lo que quieren UoW si vas a trabajar con más de un ObjectSet en su controlador para asegurar que su simplemente utilizando un contexto . Esto mantendrá sus transacciones controladas, etc.

Si va a usar múltiples objetos de texto (es decir, varios EDMX), querrá consultar el uso de UoW con MSDTC ... pero probablemente sea más de lo que quería saber . Al final, lo importante es garantizar que solo crea una instancia de lo que necesita para la acción del controlador (es decir, una instancia del contexto). No creo que vaya con Begin_Request, es posible que ni siquiera necesite el contexto para cada solicitud.

Cuestiones relacionadas