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

リポジトリ/作業単位をダンプします。 https://cpratt.co/repository-and-unit-of-work-patterns-with-entity-framework/を参照してください。 TL; DR:Entity Framework *はすでにこれらのパターンを実装しています。あなたの 'DbContext'はあなたの作業単位であり、' DbSet'はそれぞれリポジトリです。あなたがやっていることは、上に別の無意味な抽象化を追加することです。追加のメンテナンスが必要です。 –

+1

DbContextが既にこれらを実装していることは真ですが、我々はOPの意図を知らない。彼らはEFを完全に抽象化して、後でDALを後で他の技術(EFコアかもしれない)に基づいていたいと思うかもしれません。この場合、DbContextがすでにこれらのパターンを実装している場合には違いはありません。また、リポジトリ/作業単位のレイヤーを持っている場合は、DALを嘲笑して単体テストを行う方が簡単です。私の経験上、DbContextを嘲笑するのはちょっと複雑です。 –

+1

EFを後で使用したくない場合はどうすればいいですか?そして...私はあなたの提案に従ってパターンをダンプすれば。再利用可能なコードはどこに保存しますか?私がどこでも使用しているwhere節を持っていれば、どこでそれを保存するのでしょうか、私はすべての論理のために1つの場所を持っています –

答えて

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 'を返すことで何が問題になりますか? –

関連する問題