asp.net-mvc-2 - generico - patron repositorio con entity framework
Entity Framework 4 CTP 4/CTP 5 Modelo de repositorio genérico y unidad comprobable (3)
Estoy jugando con la última versión de Entity Framework CTP 5 y estoy construyendo un simple blog asp.net MVC donde solo tengo dos tablas: Publicar y Comentarios. Esto se hace completamente en POCO, solo necesito ayuda en la parte de DbContext, donde necesito que sea comprobable por unidad (usando IDbSet?) Y necesito un patrón de repositorio simple / genérico para agregar, actualizar, borrar, recuperar. Cualquier ayuda es apreciada.
Gracias.
Comience con DbContext, cree un nuevo archivo llamado Database.cs:
Database.cs
public class Database : DbContext
{
private IDbSet<Post> _posts;
public IDbSet<Post> Posts {
get { return _posts ?? (_posts = DbSet<Post>()); }
}
public virtual IDbSet<T> DbSet<T>() where T : class {
return Set<T>();
}
public virtual void Commit() {
base.SaveChanges();
}
}
Defina un IDatabaseFactory e impleméntelo con DatabaseFactory:
IDatabaseFactory.cs
public interface IDatabaseFactory : IDisposable
{
Database Get();
}
DatabaseFactory.cs
public class DatabaseFactory : Disposable, IDatabaseFactory {
private Database _database;
public Database Get() {
return _database ?? (_database = new Database());
}
protected override void DisposeCore() {
if (_database != null)
_database.Dispose();
}
}
Método de extensión desechable:
Desechable.cs
public class Disposable : IDisposable
{
private bool isDisposed;
~Disposable()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if(!isDisposed && disposing)
{
DisposeCore();
}
isDisposed = true;
}
protected virtual void DisposeCore()
{
}
}
Ahora podemos definir nuestro IRepository y nuestra RepositoryBase
IRepository.cs
public interface IRepository<T> where T : class
{
void Add(T entity);
void Delete(T entity);
void Update(T entity);
T GetById(long Id);
IEnumerable<T> All();
IEnumerable<T> AllReadOnly();
}
RepositoryBase.cs
public abstract class RepositoryBase<T> where T : class
{
private Database _database;
private readonly IDbSet<T> _dbset;
protected RepositoryBase(IDatabaseFactory databaseFactory)
{
DatabaseFactory = databaseFactory;
_dbset = Database.Set<T>();
}
protected IDatabaseFactory DatabaseFactory
{
get; private set;
}
protected Database Database
{
get { return _database ?? (_database = DatabaseFactory.Get()); }
}
public virtual void Add(T entity)
{
_dbset.Add(entity);
}
public virtual void Delete(T entity)
{
_dbset.Remove(entity);
}
public virtual void Update(T entity)
{
_database.Entry(entity).State = EntityState.Modified;
}
public virtual T GetById(long id)
{
return _dbset.Find(id);
}
public virtual IEnumerable<T> All()
{
return _dbset.ToList();
}
public virtual IEnumerable<T> AllReadOnly()
{
return _dbset.AsNoTracking().ToList();
}
}
Ahora puede crear su IPostRepository y PostRepository:
IPostRepository.cs
public interface IPostRepository : IRepository<Post>
{
//Add custom methods here if needed
Post ByTitle(string title);
}
PostRepository.cs
public class PostRepository : RepositoryBase<Post>, IPostRepository
{
public PostRepository(IDatabaseFactory databaseFactory) : base(databaseFactory)
{
}
public Post ByTitle(string title) {
return base.Database.Posts.Single(x => x.Title == title);
}
}
Por último, la UoW:
IUnitOfWork.cs
public interface IUnitOfWork
{
void Commit();
}
UnitOfWork.cs
private readonly IDatabaseFactory _databaseFactory;
private Database _database;
public UnitOfWork(IDatabaseFactory databaseFactory)
{
_databaseFactory = databaseFactory;
}
protected Database Database
{
get { return _database ?? (_database = _databaseFactory.Get()); }
}
public void Commit()
{
Database.Commit();
}
Usando en su controlador:
private readonly IPostRepository _postRepository;
private readonly IUnitOfWork_unitOfWork;
public PostController(IPostRepository postRepository, IUnitOfWork unitOfWork)
{
_postRepository = postRepository;
_unitOfWork = unitOfWork;
}
public ActionResult Add(Post post) {
_postRepository.Add(post);
_unitOfWork.Commit();
}
Tendrá que usar un contenedor IoC como StructureMap para que esto funcione. Puede instalar el mapa de estructura a través de NuGet, o si está utilizando MVC 3, puede instalar el paquete StructureMap-MVC NuGet. (Enlaces a continuación)
Install-Package StructureMap.MVC4
Install-Package StructureMap.MVC3
Mapa de estructura de paquete de instalación
Si tiene alguna pregunta solo hágamelo saber. Espero eso ayude.
Lo único que haría diferente es en la implementación, es decir, exponer el IPostRepository en la capa de servicio y tener un campo de interfaz de tipo IPostService en el controlador como otra capa de abstracción, pero este es un buen ejemplo, bueno, Paul. .
Me encanta este artículo en profundidad sobre Entity Framework 4 POCO, Repository and Specification Pattern
http://huyrua.wordpress.com/2010/07/13/entity-framework-4-poco-repository-and-specification-pattern/