3

ほぼ1年後、今回はバージョン4で新しいmvcプロジェクトを開始しています。次のリポジトリパターンの実装には利点よりも欠点の方が多いのではないかと思っていました。

public interface IRepository<T> where T : class
{
    IEnumerable<T> GetAll();

    IQueryable<T> Query(Expression<Func<T, bool>> filter);

    void Add(T entity);

    void Remove(T entity);
}

public interface IUnitOfWork
{
    void Commit();
}

public interface IDbContext : IDisposable
{
    IDbSet<T> Set<T>() where T : class;

    int SaveChanges();
}

public class DbContextAdapter : IDbContext
{
    private readonly DbContext _myRealContext;

    public DbContextAdapter()
    {
        this._myRealContext = new EstafaContext();
    }

    public void Dispose()
    {
        _myRealContext.Dispose();
    }

    public IDbSet<T> Set<T>() where T : class
    {
        return _myRealContext.Set<T>();
    }

    public int SaveChanges()
    {
        return _myRealContext.SaveChanges();
    }
}

public class SqlRepository<T> : IRepository<T> where T : class
{
    private IDbSet<T> _dbSet;

    public SqlRepository(IDbContext dbContext)
    {
        this._dbSet = dbContext.Set<T>();
    }

    public IEnumerable<T> GetAll()
    {
        return this._dbSet.ToList();
    }

    public IQueryable<T> Query(Expression<Func<T, bool>> filter)
    {
        return this._dbSet.Where(filter);
    }

    public void Add(T entity)
    {
        this._dbSet.Add(entity);
    }

    public void Remove(T entity)
    {
        this._dbSet.Remove(entity);
    }
}

public class SqlUnitOfWork : IDisposable, IUnitOfWork
{
    private IDbContext _dbContext;

    private SqlRepository<Cliente> _clientes ;

    public SqlUnitOfWork()
    {
        this._dbContext = new DbContextAdapter();
    }

    public void Dispose()
    {
        if (this._dbContext != null)
        {
            this._dbContext.Dispose();
        }
        GC.SuppressFinalize(this);
    }

    public IRepository<Cliente> Clientes
    {
        get { return _clientes ?? (_clientes = new SqlRepository<Cliente>(_dbContext)); }
    }       

    public void Commit()
    {
        this._dbContext.SaveChanges();
    }
}

このようにして、SqlUnitOfWork を使用してすべてのリポジトリを 1 つのポイントから管理できます。以前のプロジェクトでこのデザインを使用しましたが、かなりうまく機能しましたが、効率的ではなく、冗長であると感じています。このような抽象化層を追加する価値はありますか?

前もって感謝します!

4

2 に答える 2

1

私の実装はあなたが持っているものとまったく同じではありませんが、私にはかなりしっかりしているようです.

私が通常行うその他の唯一の変更は、次のように、エンティティ タイプのリポジトリごとに特定のインターフェイスを定義することです。

public interface IClienteRepository : IRepository<Cliente>
{
  IEnumerable<Cliente> GetByName(string firstName);
  // etc
}

そうすれば、CRUD 操作にすべてのリポジトリを汎用的に使用できますが、同じリポジトリを使用して一部のクエリ ロジックを抽象化することもできます。リポジトリのユーザーは、自分が何を望んでいるのかを知るだけでよく、それを取得する方法は知りません。

もちろん、これはもう少し面倒で、追加機能を追加するリポジトリの具体的な実装を作成する必要がありますが、とにかくアプリケーションを介して他の場所にあるクエリロジックをカプセル化するだけです.

于 2012-12-04T03:11:31.510 に答える
1

それ以上の欠点や利点があるかどうかはわかりませんが、何年にもわたって、このタイプのリポジトリパターンはますます役に立たなくなってきました。その場でデータベースやデータソースを切り替えることが現実的な可能性がない限り、または非常識なレベルのモック・ザ・ユニバースのテストカバレッジが必要な場合を除き、それは価値があるよりも面倒だと思います.

個人的な好みですが、データ アクセス方法をもう少し明示的にするのが好きです。たとえば、モデルをビューに返す場合、データベース内のテーブルとは明らかに異なって見えます。だから私はメソッドではなく、GetAllModelXメソッドが欲しいGetAllDbTableRows

では、この変換コードはどこに格納されるのでしょうか? コントローラーで?エンティティをモデルに変換する別のデータ アクセス レイヤー? 正しいか間違った答えさえありますか?おそらくそうではありません。

私は間違いなくここで少し悪魔の擁護者を演じていますが、私の経験では、モデルを返し/受け入れ、すべてのクエリ/CRUDding/UnitOfWork を処理するデータアクセスレイヤーを支持して、この汎用リポジトリ設計から離れました通常は EF を使用するデータベース。しかし、繰り返しになりますが、私はあまりモッキングを行わず、より多くの統合テストを行う古典的な単体テスト担当者です。

于 2012-12-04T03:27:11.213 に答える