我正在尝试使用Generic Repository创建一个库,以便以后在我的MVC App中使用。代码如下......
public abstract class BaseEntity
{
}
public interface IEntity<T>
{
T Id { get; set; }
}
public abstract class Entity<T> : BaseEntity, IEntity<T>
{
public virtual T Id { get; set; }
}
public interface IAuditableEntity
{
int? UsuarioId { get; set; }
DateTime CreatedDate { get; set; }
string CreatedBy { get; set; }
DateTime UpdatedDate { get; set; }
string UpdatedBy { get; set; }
}
public abstract class AuditableEntity<T> : Entity<T>, IAuditableEntity
{
public int? UsuarioId { get; set; }
public DateTime CreatedDate { get; set; }
public string CreatedBy { get; set; }
public DateTime UpdatedDate { get; set; }
public string UpdatedBy { get; set; }
}
public interface IGenericRepository<T> where T : BaseEntity
{
IEnumerable<T> GetAll();
IEnumerable<T> GetByUsuarioId(int usuarioId);
T GetById(int id);
T Add(T entity);
T Delete(T entity);
void Edit(T entity);
void Save();
}
public class GenericRepository<T> : IGenericRepository<T>
where T : BaseEntity
{
protected DbContext _entities;
protected readonly IDbSet<T> _dbset;
public GenericRepository(DbContext context)
{
_entities = context;
_dbset = context.Set<T>();
}
public virtual IEnumerable<T> GetAll()
{
return _dbset.AsEnumerable<T>();
}
public IEnumerable<T> FindBy(Expression<Func<T, bool>> predicate)
{
IEnumerable<T> query = _dbset.Where(predicate).AsEnumerable();
return query;
}
public virtual IEnumerable<T> GetByUsuarioId(int usuarioId)
{
// NO SÉ COMO IMPLEMENTAR ESTE METODO!!!!!
return null;
// NO SÉ COMO IMPLEMENTAR ESTE METODO!!!!!
}
public virtual T GetById(int id)
{
return _dbset.Find(id);
}
public virtual T Add(T entity)
{
return _dbset.Add(entity);
}
public virtual T Delete(T entity)
{
return _dbset.Remove(entity);
}
public virtual void Edit(T entity)
{
_entities.Entry(entity).State = EntityState.Modified;
}
public virtual void Save()
{
_entities.SaveChanges();
}
}
这些是我的一些课程POCO ......
public class Documento : AuditableEntity<int>
{
public string Descripcion { get; set; }
public string Foto { get; set; }
public virtual Usuario Usuario { get; set; }
}
public class Gasto : AuditableEntity<int>
{
public int? TaxiId { get; set; }
public int TipoGastoId { get; set; }
public DateTime Fecha { get; set; }
public double Importe { get; set; }
public int Kilometros { get; set; }
public string Descripcion { get; set; }
public string Foto { get; set; }
public virtual Usuario Usuario { get; set; }
public virtual Taxi Taxi { get; set; }
public virtual TipoGasto TipoGasto { get; set; }
public virtual PartidaTarjetas PartidaTarjetas { get; set; }
public virtual ICollection<Tarea> Tareas { get; set; }
public int? PartidaTarjetasId { get; set; }
public Gasto()
{
Tareas = new List<Tarea>();
}
}
public class Nivel : Entity<int>
{
public string Descripcion { get; set; }
public string PaginaInicio { get; set; }
public virtual ICollection<Usuario> Usuarios { get; set; }
public Nivel()
{
Usuarios = new List<Usuario>();
}
}
我的问题是它不会实现方法......
public virtual IEnumerable<T> GetByUsuarioId(int usuarioId)
{
// NO SÉ COMO IMPLEMENTAR ESTE METODO!!!!!
return null;
// NO SÉ COMO IMPLEMENTAR ESTE METODO!!!!!
}
这是一种通用方法,只有在IAuditable类型时才返回结果...,必须是某些东西......
public virtual IEnumerable<T> GetByUsuarioId(int usuarioId)
{
return _dbset.FindBy(c => c.UsuarioId == usuarioId);
}
你帮我吗?
感谢。
Hello C Bauer ......
请注意......
public abstract class BaseEntity
{
}
public interface IEntity<T>
{
T Id { get; set; }
}
public abstract class Entity<T> : BaseEntity, IEntity<T>
{
public virtual T Id { get; set; }
}
public interface IAuditableEntity
{
int? UsuarioId { get; set; }
DateTime CreatedDate { get; set; }
string CreatedBy { get; set; }
DateTime UpdatedDate { get; set; }
string UpdatedBy { get; set; }
}
public abstract class AuditableEntity<T> : Entity<T>, IAuditableEntity
{
public int? UsuarioId { get; set; }
public DateTime CreatedDate { get; set; }
public string CreatedBy { get; set; }
public DateTime UpdatedDate { get; set; }
public string UpdatedBy { get; set; }
}
我的GenericRepositry是..
public interface IGenericRepository<T> where T : BaseEntity
然后现在¿?
public interface IGenericRepository<T> where T : ¿¿ ??
答案 0 :(得分:2)
您可以实现类型化存储库扩展类,以便它仅适用于IRepository<IAuditable>
:
public static class Extensions
{
public static IEnumerable<IAuditable> GetUsuarioById(this IRepository<IAuditable> repository, int id)
{
return repository.FindBy(audible => audible.Id == id);
}
}
编辑:
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace StackOverflowPlayground
{
class JesusPlayground
{
public JesusPlayground()
{
var auditableRepo = new AuditableRepo();
auditableRepo.GetUsuarioById(1);
var otherRepo = new OtherRepo();
//otherRepo. (does not have GetUsuarioById
var auditableRepoNotUsingTheActualClass = new GenericRepository<IAuditable>();
auditableRepoNotUsingTheActualClass.GetUsuarioById(1); //still works!
}
}
public static class Extensions
{
public static IEnumerable<IAuditable> GetUsuarioById(this IRepository<IAuditable> repository, int id)
{
return repository.FindBy(audible => audible.Id == id);
}
}
public class OtherRepo : IRepository<OtherType>
{
public IEnumerable<OtherType> FindBy(Expression<Func<OtherType, bool>> expr)
{
throw new NotImplementedException();
}
}
public class OtherType
{
}
public interface IAuditable
{
int Id { get; set; }
}
public interface IRepository<T>
{
IEnumerable<T> FindBy(Expression<Func<T, bool>> expr);
}
public class GenericRepository<T> : IRepository<T>
{
public IEnumerable<T> FindBy(Expression<Func<T, bool>> expr)
{
throw new NotImplementedException();
}
}
class AuditableRepo : IRepository<IAuditable>
{
public IEnumerable<IAuditable> FindBy(Expression<Func<IAuditable, bool>> expr)
{
throw new NotImplementedException();
}
}
}
答案 1 :(得分:0)
如果这始终是真的,请将其添加到您的基本虚拟方法中,以便在整个代码库中强制执行。
public virtual IEnumerable<T> GetByUsuarioId(int usuarioId)
{
if (!typeof(T).GetInterfaces().Contains(typeof(IAuditable))
return Enumerable.Empty<T>(); // per OffHeGoes' suggestion
return _dbset.FindBy(c => c.UsuarioId == usuarioId);
}
当然,根据以下评论(并且谢谢大家),这个解决方案存在性能问题和潜在的逻辑隐藏问题。它不是解决问题的最优雅方式,但确实解决了这个问题。
答案 2 :(得分:0)
不确定您是如何计划在代码中使用这些存储库的(因此这可能不一定与您如何使用它们有关),但为什么不添加另一层继承?
在GenericRepository中:
public virtual IEnumerable<T> GetByUsuarioId(int usuarioId)
{
//TODO: default behaviour
}
然后为Auditable类型创建一个存储库:
public class AuditableRepository<T> : GenericRepository<T>
where T: IAuditableEntity, BaseEntity
您实施相关逻辑:
public override IEnumerable<T> GetByUsuarioId(int usuarioId)
{
//TODO: auditable behaviour
}
显然,这确实意味着你消费代码必须知道不同的存储库,但正如我所说,这取决于你如何使用它们。如果你使用的是IoC,你可以注入正确的存储库。