¿Está bien crear un objeto DataContext de Entity Framework y disponerlo en un bloque de uso en cada uno de mis métodos CRUD?

10

Estoy creando una aplicación wpf que implementa las siguientes características:

  1. Tome la entrada del usuario y lea datos de bases de datos
  2. realizar algunos cálculos al respecto
  3. Muestre al usuario en múltiples tipos de vistas y escriba los cambios de nuevo en db

Arquitectura propuesta: Base de datos -> Entity Framework -> Repository -> Business Logic -> Data Service -> ViewModel

Razones para usar esta arquitectura: múltiples escenarios presentes en la aplicación (múltiples vistas) y múltiples bases de datos. Por lo tanto, estoy dispuesto a utilizar el repositorio en el medio para la abstracción.

Una advertencia es que el contexto durará mucho tiempo si se implementa el repositorio. Para superar esto, ¿está bien crear un contexto y disponerlos en un bloque using () en cada uno de los métodos crudos?

siéntase libre de sugerir enfoques alternativos.

Skyuppercut
fuente
Eche un vistazo a este hilo que es similar a su consulta. stackoverflow.com/questions/21875816/…
Gopinath

Respuestas:

16

Utilice un objeto DbContext por acceso a datos o transacción.

DbContextes un objeto liviano; Está diseñado para usarse una vez por transacción comercial. Hacer DbContextun Singleton y reutilizarlo en toda la aplicación puede causar otros problemas, como problemas de concurrencia y pérdida de memoria.

DbContextesencialmente implementa una Unidad de Trabajo. Trátelo en consecuencia.

No deseche objetos DbContext.

Aunque los DbContextimplementos IDisposable, no debe desecharlos manualmente, ni debe envolverlos en una usingdeclaración. DbContextmaneja su propia vida; cuando se complete su solicitud de acceso a datos, DbContextse cerrará automáticamente la conexión de la base de datos por usted.

Para comprender por qué este es el caso, considere lo que sucede cuando ejecuta una instrucción Linq en una colección de entidades desde a DbContext. Si devuelve un perezoso de carga IQueryablede su método de acceso de datos, se pone de pie una tubería que no se ejecuta realmente hasta que el cliente obliga a algunos datos de él (llamando FirstOrDefault(), ToList()o interactuando sobre ella).

Lecturas adicionales
¿Siempre tengo que llamar a Dispose () en mis objetos DbContext?
¿Por qué no debería usar Singleton DataContexts en Entity Framework
Retornando IEnumerable<T>vs. IQueryable<T>
Deberían retornar los repositorios IQueryable?

Robert Harvey
fuente
44
Si bien estoy seguro de que alguien presentará algún tipo de caso excepcional para esto, honestamente no puedo encontrar un buen caso de uso para devolver un IQueryable no materializado de sus clases de acceso a datos. Eso solo le da al código de llamadas la capacidad de acceder a su acceso a datos (algo que probablemente no tiene que ver con hacer) y arruinar las cosas. Dicho esto, ¿es realmente una gran preocupación preocuparse por el uso de usingbloques? ¿O simplemente no estoy pensando en algún caso en el que valga la pena usar un IQueryable como usted sugiere?
Becuzz
@Becuzz: El DbContextes responsable de administrar su propia vida. Mi sugerencia es dejar que haga eso; funcionará si está usando IQueryableo IEnumerable. El caso de uso más obvio que se me ocurre para la carga diferida es cuando devuelve algún objeto ViewModel con una colección relacionada, pero la colección nunca se usa (o solo se usa parcialmente). IQueryablele permite evitar el costo de recuperar registros no utilizados.
Robert Harvey
3
Entiendo todo eso, es solo que me quemé al hacer que la gente devuelva IQueryables por todo el lugar. Y luego, algo más arriba en la cadena agregó algunas cosas que hicieron una consulta horriblemente mala (desde la perspectiva del rendimiento de la base de datos). Y ese fue un error divertido para rastrear. Como tal, tuve la oportunidad de pensar si devolver una IQueryable es una buena idea. Y nunca podría pensar en un momento en que valiera la pena el mantenimiento. (cont.)
Becuzz
44
@RobertHarvey, ¿cuál es exactamente el punto de una capa de repositorio si está devolviendo un IQueryable al cliente? Básicamente, le está dando al cliente la opción de escribir consultas, seguro que no serán consultas SQL pero, sin embargo, son consultas (solo escritas usando C #) y estarán por todas partes. Si un repositorio está devolviendo IQueryable, entonces también puede tirar el repositorio.
CodificaciónYoshi
8
@RobertHarvey No estoy de acuerdo con no disponer de DbContext y no estoy de acuerdo con el artículo mencionado. La idea es codificar contra la interfaz y la interfaz me dice que es IDisposable. No voy a escribir mi código basado en el funcionamiento interno de cómo el equipo de EF ha implementado DbContext o perseguir a los desarrolladores de ese equipo; pueden cambiarlo en cualquier momento que lo deseen. Tampoco me voy a pedir a mí mismo ni a otros desarrolladores que comiencen a profundizar en el funcionamiento interno de cada clase para ver si IDisposable es realmente útil. He trabajado demasiado para que los desarrolladores de mi equipo se deshagan solo de preguntarles no siempre.
CodificaciónYoshi
-3

Idealmente, el contexto debe ser inicializado y terminado para una sola transacción. En su caso, el contexto se debe instanciar en Business Logic y pasar al Repositorio para la lectura / escritura de datos.

Gopinath
fuente
2
Sí, porque la lógica de negocios es más fácil de mantener cuando se acopla estrechamente al acceso a datos ... :(
TheCatWhisperer
-3

Si llama a DbContext en cada método de su aplicación, experimentará una pérdida de memoria. Use una sola instancia de DbContext. Vea el comentario en el siguiente ejemplo:

public bool IsInStock(int _ProductId)
{
  var result = false;

  try
  {
    using (var dataService = new StoreDbDataService()) // NB: This line on each method will eventually cause memory leak.
    {
      result = dataService.IsInStock(_ProductId);
    }
  }
  catch (Exception ex)
  {
    Log.LogException(ex);
  }

  return result;
}
Joseph Majase Sithole
fuente
1
¿Puede explicar por qué llamar a DbContext causaría una pérdida de memoria? El comentario en la fuente no me ayuda a entenderlo. Supongo que el bloque de uso provocaría que se llamara a Dispose en el StoreDBDataService, que eventualmente limpia todos los recursos asignados, ¿no?
Kasper van den Berg
Esto es básicamente el clip de "permiso" de Ron Swanson pero en código.
Dagrooms