2014-12-15 19 views
5

Tôi đang cố gắng tạo một thư viện với một kho lưu trữ chung để sử dụng sau này trong ứng dụng MVC của tôi. Mã này được như sau ...Generic Repository thêm phương thức tùy chỉnh

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(); 
    } 
} 

Và đây là một số lớp học của tôi 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>(); 
    } 
} 

Vấn đề của tôi là nó sẽ không thực hiện phương pháp này ...

public virtual IEnumerable<T> GetByUsuarioId(int usuarioId) 
    { 
     // NO SÉ COMO IMPLEMENTAR ESTE METODO!!!!! 
     return null; 
     // NO SÉ COMO IMPLEMENTAR ESTE METODO!!!!! 
    } 

Đây là phương pháp chung mà chỉ trả về kết quả khi là loại IAuditable ..., phải là một cái gì đó ...

public virtual IEnumerable<T> GetByUsuarioId(int usuarioId) 
    { 
     return _dbset.FindBy(c => c.UsuarioId == usuarioId); 
    } 

Bạn có thể giúp tôi không ?, Cảm ơn.

Hello C Bauer ...

Lưu ý rằng ...

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; } 
} 

Và GenericRepositry của tôi là ..

public interface IGenericRepository<T> where T : BaseEntity 

Sau đó tại ¿?

public interface IGenericRepository<T> where T : ¿¿ ?? 
+0

Bạn chỉ đang cố gắng đảm bảo rằng tham số chung 'T' thực hiện' IAuditable'? Đó là mục đích của các ràng buộc chung: http://msdn.microsoft.com/en-us/library/d5x73970.aspx. –

+0

Ví dụ: Documento.cs triển khai AuditableEntity ... –

+0

@ JesúsSánchez Xin chào Chúa Giêsu, bạn nên tránh chỉnh sửa người dùng khác vào câu trả lời của bạn. Thay vào đó, hãy thêm nhận xét để trả lời giải quyết vấn đề bạn gặp phải với mã của họ. –

Trả lời

0

Nếu điều này luôn đúng, hãy thêm nó vào phương pháp ảo cơ sở của bạn sẽ được thực thi trong suốt mã của bạn.

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); 
} 

Được cấp, theo nhận xét bên dưới (và cảm ơn tất cả), có cả các mối quan tâm về hiệu suất và mối quan tâm ẩn logic tiềm tàng với giải pháp này. Nó hầu như không phải là cách thanh lịch nhất để giải quyết vấn đề, nhưng nó thực sự giải quyết nó.

+0

Tôi sẽ ném một NotImplementedException hoặc một cái gì đó, như trở về null là một sự nhầm lẫn. –

+0

@CBauer Tôi hoàn toàn đồng ý. Điều đó nói rằng, mã của OP đang trở về null và tôi không muốn diễn giải ý định của anh ta như những gì anh ta muốn quay trở lại. –

+0

C Bauer, tôi đã chỉnh sửa câu hỏi ban đầu của mình, hãy kiểm tra ... Cảm ơn –

2

Bạn có thể thực hiện một lớp mở rộng kho gõ để nó chỉ hoạt động trên IRepository<IAuditable>:

public static class Extensions 
    { 
     public static IEnumerable<IAuditable> GetUsuarioById(this IRepository<IAuditable> repository, int id) 
     { 
      return repository.FindBy(audible => audible.Id == id); 
     } 
    } 

Edit:

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(); 
     } 
    } 
} 
+0

Tôi có nên sử dụng hai kho lưu trữ không? ... GenericRepository và AuditableRepo ?? –

+0

Vâng, điều đó phụ thuộc vào cách ứng dụng của bạn được kiến ​​trúc. Tôi đã luôn sử dụng kho lưu trữ để chuẩn hóa cách truy cập dữ liệu được xây dựng. Bạn có thể cũng giống như dễ dàng làm: 'var auditableRepoNotUsingTheActualClass = new GenericRepository ();' 'auditableRepoNotUsingTheActualClass.GetUsuarioById (1); // vẫn hoạt động! ' –

+0

@ JesúsSánchez Bạn vẫn có thể sử dụng mã ban đầu của mình, ví dụ tôi đăng chỉ là một mẫu nhỏ của mã và cách nó hoạt động. –

0

Không chắc làm thế nào bạn đang có kế hoạch trên sử dụng những kho tại của bạn mã (vì vậy điều này có thể không nhất thiết phải làm việc với cách bạn đang tiêu thụ chúng), nhưng tại sao không thêm một lớp thừa kế khác?

Trong GenericRepository của bạn:

public virtual IEnumerable<T> GetByUsuarioId(int usuarioId) 
{ 
    //TODO: default behaviour 
} 

Sau đó tạo một kho lưu trữ cho các loại Auditable:

public class AuditableRepository<T> : GenericRepository<T> 
    where T: IAuditableEntity, BaseEntity 

Trong đó bạn thực hiện logic liên quan:

public override IEnumerable<T> GetByUsuarioId(int usuarioId) 
{ 
    //TODO: auditable behaviour 
} 

Rõ ràng điều này không có nghĩa là mà bạn tiêu thụ mã phải biết về các kho lưu trữ khác nhau, nhưng như tôi nói, tôi t phụ thuộc vào cách bạn đang sử dụng chúng. Nếu bạn đang sử dụng IoC, bạn có thể tiêm các kho lưu trữ chính xác.

Các vấn đề liên quan