patron - Patrón de repositorio en Entity framework 4 ¿Cuándo deberíamos disponer?
patron repositorio net core (1)
Sí, debe disponer el contexto incluso si está utilizando el repositorio. No está claro qué ventaja le da su implementación de Repositorio porque todavía está proporcionando ObjectContext como parámetro del constructor, ¿no es así?
En mi opinión, la razón principal para usar Repository y UnitOfWork personalizado es la persistencia ignorancia = ocultar el código EF de las capas superiores de la aplicación porque ObjectContext + ObjectSet son la implementación del repositorio y los patrones de unidad de trabajo.
Si estoy usando el repositorio, siempre estoy envolviendo todo el código de EF, por lo que la interfaz pública de mi repositorio no proporciona ninguna información sobre la infraestructura relacionada con EF. En ese caso, depende de mí cómo trato con ObjectContext.
Para escenarios sencillos de CRUD, puedo ajustar la creación de contexto y la eliminación en cada método de repositorio. En escenarios más complejos, estoy usando una clase adicional: UnitOfWork (UoW), que envuelve la creación y disposición del contexto y activa los cambios guardados en la base de datos. También actúa como fábrica para todos los repositorios y pasa instancia de contexto creado a constructores de repositorios.
La mayoría de las veces estoy programando servicios o aplicaciones web, así que estoy lidiando con objetos separados. Siempre estoy usando una sola instancia UoW para el procesamiento de solicitudes. Por lo tanto, la UoW se crea al inicio del procesamiento de la solicitud y se publica al final del procesamiento de la solicitud. En el caso de las aplicaciones WinForms / WPF y los objetos adjuntos, creo que la buena idea es tener la instancia de UoW / ObjectContext "por formulario"; hay un article describe este enfoque con una sesión de NHibernate (igual que EF ObjectContext) en la revista MSDN.
Algunas implementaciones iniciales de los patrones de UnitOfWork y Repository:
Contenedor de contexto y fábrica abstracta para repositorios
public interface IUnitOfWork
{
IRepository<MyEntity> MyEntityRepository { get; }
// Repositories for other entities
SaveChanges();
}
Repositorio para entidades separadas
public interface IRepository<T> where T : class
{
IQueryable<T> GetQuery();
void Insert(T entity);
void Delete(T entity);
// In very complex scenarios with big object graphs you will probably give up
// using detached approach and you will always load your entities from DB before
// deleting or updating them. In such case you will not need Update method at all.
void Update(T entity);
}
Implementación desechable del marco de Enitity de ajuste UnitOfWork
public class UnitOfWork : IUnitOfWork, IDisposable
{
private ObjectContext _context = null;
public UnitOfWork(string connectionString)
{
if (String.IsNullOrEmpty(connectionString)) throw new ArgumentNullException("connectionString");
_context = new ObjectContext(connectionString);
}
private IRepository<MyEntity> _myEntityRepository;
public IRepository<MyEntity> MyEntityRepository
{
get
{
return _myEntityRepository ?? (_myEntityRepository = new GeneralRepository<MyEntity>(_context));
}
}
public void SaveChanges()
{
_context.SaveChanges();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_context != null)
{
_context.Dispose();
_context = null;
}
}
}
}
Implementación del repositorio base
public class GeneralRepository<T> : IRepository<T> where T : class
{
private ObjectSet<T> _set;
private ObjectContext _context;
public GeneralRepository(ObjectContext context)
{
if (context == null) throw new ArgumentNullException("context");
_context = context;
_set = context.CreateObjectSet<T>();
}
// Override this method for example if you need Includes
public virtual IQueryable<T> GetQuery()
{
return _set;
}
// Override following methods if you are working with object graphs.
// Methods do not execute operations in database. It is responsibility of
// UnitOfWork to trigger the execution
public virtual void Insert(T entity)
{
if (entity == null) throw new ArgumentNullException("entity");
_set.AddObject(entity);
}
// These impelementations are for detached scenarios like web application
public virtual void Delete(T entity)
{
if (entity == null) throw new ArgumentNullException("entity");
_set.Attach(entity);
_set.DeleteObject(entity);
}
public virtual void Update(T entity)
{
if (entity == null) throw new ArgumentNullException("entity");
_set.Attach(entity);
_context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
}
}
Uso al seleccionar datos
using (var uow = new UnitOfWork(connectionString))
{
var entity = uow.MyEntitiesRepository.GetQuery().Single(e => e.Id == 1);
// Do something with entity
}
Uso cuando se modifican datos
using (var uow = new UnitOfWork(connectionString))
{
uow.MyEntitiesRepository.Update(entity);
uow.SaveChanges();
}
Como novedad en EF, he notado que usar un patrón de repositorio realmente puede simplificar las cosas y también me permitirá hacer algunas burlas. Hasta ahora, bien.
Mi pregunta
Un uso típico de objectContext es destruir lo antes posible, ver más abajo.
using (var context = new SchoolEntities())
{
context.AddToDepartments(department);
context.SaveChanges();
}
Utilizando el patrón Repository, he notado que nadie usa el "Uso del patrón", por ejemplo
using (var repository= new Repository<Student>(new MyContext))
{
repository.Add(myStudentEntity)
repository.SaveChanges();
}
¿Debería ser la idea de que deberíamos deshacernos del contexto lo antes posible o, de lo contrario, la memoria podría perder o hacerse muy grande?
¿Alguien puede aclarar? Muchas gracias.