0

응용 프로그램에 사용할 리포지토리 패턴이 있습니다. 모든 것이 오늘 완벽하게 작동합니다. 그러나 다른 모델과의 관계를 포함시킬 수있는 능력을 추가하고 싶습니다.C#으로 저장소 패턴과 관계를 어떻게 추가 할 수 있습니까?

여기에 내 현재 IRepository

public interface IRepository<TModel> 
    where TModel : class 
{ 

    // Get records by it's primary key 
    TModel Get(int id); 

    // Get all records 
    IEnumerable<TModel> GetAll(); 

    // Get all records matching a lambda expression 
    IEnumerable<TModel> Find(Expression<Func<TModel, bool>> predicate); 

    // Get the a single matching record or null 
    TModel SingleOrDefault(Expression<Func<TModel, bool>> predicate); 

    // Add single record 
    TModel Add(TModel entity); 

    // Add multiple records 
    IEnumerable<TModel> AddRange(IEnumerable<TModel> entities); 

    // Remove records 
    void Remove(TModel entity); 

    // remove multiple records 
    void RemoveRange(IEnumerable<TModel> entities); 
} 

여기

public class EntityRepository<TEntity> : IRepository<TEntity> 
where TEntity : class 
{ 
protected readonly DbContext Context; 

protected readonly DbSet<TEntity> DbSet; 

public EntityRepository(DbContext context) 
{ 
    Context = context; 
    DbSet = context.Set<TEntity>(); 
} 

public TEntity Get(int id) 
{ 
    return DbSet.Find(id); 
} 

public IEnumerable<TEntity> GetAll() 
{ 
    return DbSet.ToList(); 
} 

public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate) 
{ 
    return DbSet.Where(predicate); 
} 

public TEntity SingleOrDefault(Expression<Func<TEntity, bool>> predicate) 
{ 
    return DbSet.SingleOrDefault(predicate); 
} 

public TEntity Add(TEntity entity) 
{ 
    TEntity record = DbSet.Add(entity); 

    return record; 
} 

public IEnumerable<TEntity> AddRange(IEnumerable<TEntity> entities) 
{ 
    IEnumerable<TEntity> records = DbSet.AddRange(entities); 

    return records; 
} 

public void Remove(TEntity entity) 
{ 
    DbSet.Remove(entity); 
} 

public void RemoveRange(IEnumerable<TEntity> entities) 
{ 
    DbSet.RemoveRange(entities); 
} 

지금, 나는 내가 게으른로드를 처리 할 수 ​​있도록 다른 방법을 추가 할 내 법인의 구현입니다. 다른 말로하면, 내가 작업 클래스 다음

public sealed class UnitOfWork : IUnitOfWork 
{ 
    private bool Disposed = false; 
    private readonly ModuleContext Context; 

    public ITaskRepository Tasks { get; private set; } 

    public UnitOfWork(ModuleContext context) 
    { 
     Context = context; 
     Tasks = new TaskRepository(Context); 
    } 

    public int Save() 
    { 
     return Context.SaveChanges(); 
    } 

    public void Dispose() 
    { 
     Dispose(true); 
    } 

    private void Dispose(bool disposing) 
    { 
     if (!Disposed && Context != null && disposing) 
     { 
      Context.Dispose(); 
     } 

     Disposed = true; 
    } 
} 

내 단위에서 다음이

using(var con = new UnitOfWork()) 
{ 
    var task = con.Tasks.With(x => x.Owner).GetAll(); 
} 

같은 것을 할 수 있기를 원하는 것은 내 작업 모델이다

public class Task 
{ 
    public string Name { get; set; } 

    [ForeignKey("Client")] 
    public int ClientId { get; set; } 

    [ForeignKey("Owner")] 
    public int? OwnerId { get; set; } 

    public virtual Client Client { get; set; } 
    public virtual User Owner { get; set; } 
} 

어떻게 다른 모델에 관계를 포함시킬 수있는 방법을 추가합니까?

+0

저장소/작업 단위 (UOW) 작업을 덤프하십시오. 참조 : https://cpratt.co/repository-and-unit-of-work-patterns-with-entity-framework/. TL : DR : Entity Framework * 이미 * 이러한 패턴을 구현합니다. 'DbContext'는 작업 단위이고'DbSet'은 저장소입니다. 당신이하고있는 일은 그 위에 추가로 의미없는 추상화를 추가하는 것입니다. 추가적인 유지 관리가 필요합니다. –

+1

DbContext가 이미 이러한 기능을 구현하고있는 것은 사실이지만 OP의 의도는 알 수 없습니다. DFM은 나중에 다른 기술 (어쩌면 EF 코어)을 기반으로 할 수 있으므로 완전히 EF를 추상화하려는 것일 수 있습니다. 이 경우, DbContext가이 패턴을 벌써 구현하고있는 경우는, 차이는 없습니다. 또한 저장소/작업 단위 단위가있는 경우 DAL을 조롱하면 단위 테스트가 더 쉬워 질 수 있습니다. 내 경험에 비추어 볼 때, DbContext 조롱은 다소 복잡합니다. –

+1

그리고 나중에 EF를 사용하고 싶지 않은 경우 어떻게해야합니까? 그리고 ... 당신의 제안대로 패턴을 버리면. 재사용 가능한 코드는 어디에 저장해야합니까? 내가 어디에서나 사용하는 where 절을 가지고 있다면, 나는 그것을 저장할 것이므로, 나는 모든 논리에 대해 하나의 장소를 가진다. –

답변

0

가능한 포함 식 목록을 허용하도록 리포지토리 인터페이스에 메서드에 대한 오버로드를 추가합니다. 예 :

public IEnumerable<TEntity> FindAll(params Expression<Func<TEntity,object>> includes) 
{ 
    var query = DbSet; 
    foreach (var include in includes) 
    { 
     query = query.Include(include); 
    } 
    return query.ToList(); 
} 

그리고 당신은 쓸 수 있습니다 :이 같은 것을 할 수있는 필터링 된 경우를 들어

uow.Tasks.GetAll(t=>t.Owner); 

:

public IEnumerable<TEntity> Find(Expression<Func<TEntity,bool>> filter, params Expression<Func<TEntity,object>> includes) 
{ 
    var query = DbSet; 
    foreach (var include in includes) 
    { 
     query = query.Include(include); 
    } 
    return query.Where(filter).ToList(); 
} 

을 그리고 당신은 그냥 쓸 수 있습니다 :

uow.Tasks.Find(t=>t.Something==2, t=>t.Owner); 
+0

감사합니다. 필터를 적용하고 관계를 포함시키려는 경우는 어떻습니까? .where(). include() ... –

+0

필터링 된 사례에 대한 업데이트 된 예제를 참조하십시오. –

+0

업데이트 해 주셔서 감사합니다. 그러나'IQueryable '을 반환하는 것이 잘못된 것입니까? –