6

インターフェース

public interface IDinnerRepository 
{
    IQueryable<Dinner> FindAllDinners();
    IQueryable<Dinner> FindDinnersByText(string q);

    Dinner GetDinner(int id);

    void Add(Dinner dinner);
    void Delete(Dinner dinner);

    void Save();
}

上記のインターフェースから継承されたクラス

public class DinnerRepository : NerdDinner.Models.IDinnerRepository
{
    NerdDinnerEntities db = new NerdDinnerEntities();

    Public IQueryable<Dinner> FindDinnersByText(string q)
    {
         return db.Dinners.Where(d => d.Title.Contains(q)
             || d.Description.Contains(q)
             || d.HostedBy.Contains(q));
    }

    public IQueryable<Dinner> FindAllDinners()
    {
         return db.Dinners;
    }

    public Dinner GetDinner(int id)
    {
        return db.Dinners.SingleOrDefault(d => d.DinnerID == id);
    }

    public void Add(Dinner dinner)
    {
        db.Dinners.AddObject(dinner);
    }

    public void Delete(Dinner dinner)
    {
        foreach (RSVP rsvp in dinner.RSVPs.ToList())
            db.RSVPs.DeleteObject(rsvp);

        db.Dinners.DeleteObject(dinner);
   }

   public void Save()
   {
        db.SaveChanges();
   }
}

プログラムでの使用法

public class DinnerOperation
{
    DinnerRepository dr = new DinnerRepository();

    // insert
    public void InsertDinner()
    {
        Dinner dinner = dr.GetDinner(5);
        dr.Dinner.Add(dinner);
        dr.Save();
    }

    // delete
    public void DeleteDinner()
    {
        Dinner dinner = dr.GetDinner(5);
        dr.Dinner.Delete(dinner);
        dr.Save();
    }
}

そして、リポジトリデザインパターンを使用せずに...

public class DinnerOperation
{
    DinnerEntities entity = new DinnerEntities();

    // insert
    public void InsertDinner()
    {
        Dinner dinner = entity.Dinners.Find(5);
        entity.Dinner.Add(dinner);
        entity.SaveChanges();
    }

    // delete
    public void DeleteDinner()
    {
        Dinner dinner = entity.Dinners.Find(5);
        entity.Dinner.Remove(dinner);
        entity.SaveChanges();
    }
}

質問

ここでは、なぜデザインパターンを使用したのか理解できません。このようにEntityFrameworkでリポジトリデザインパターンを使用する場合、何の意味もありません。

エンティティフレームワークでデザインパターンを使用するにはどうすればよいですか?エンティティフレームワークでデザインパターンを使用する意味があるのはいつですか?

4

3 に答える 3

7

あなたはほとんどそれを手に入れました。まず、ディナー操作クラスをリファクタリングして、リポジトリの実装をそれに注入できるようにします。

public class DinnerOperation
{
  private IDinnerRepository dr;
  public DinnerOperation( IDinnerRespository repository ) {
     this.dr = repository;
  }

  // insert
  public void InsertDinner()
  {
      Dinner dinner = dr.GetDinner(5);
      dr.Dinner.Add(dinner);
      dr.Save();
  }

  // delete
  public void DeleteDinner()
  {
      Dinner dinner = dr.GetDinner(5);
      dr.Dinner.Delete(dinner);
      dr.Save();
  }
}

次に、さまざまなリポジトリを実装します。

public class EntityFrameworkDinnerRepository : IDinnerRepository
public class NHibernateDinnerRepository : IDinnerRepository
public class Linq2SqlDinnerRepository : IDinnerRepository
public class MockDinnerRepository : IDinnerRepository
....

次に、必要なリポジトリを使用します。

var repository = new ....Repository();
var operation = new DinnerOperation( repository );

operation.GetDinner(5);

リポジトリは、具体的なデータプロバイダーを抽象化するために使用され、アーキテクチャをより使いやすくします。

nHibernateに切り替えたいですか?

どこにでもEntityFrameworkがあると、苦痛になります。簡単です。リポジトリを使用する場合は、別のリポジトリを挿入するだけで、ビジネスロジックを変更する必要はありません。

ビジネスロジックを単体テストしたいですか?

あなたが具体的なデータプロバイダーに固執しているなら、苦痛です。簡単です。リポジトリがある場合は、データベースを使用しないインメモリリポジトリを挿入するだけです。

今それを手に入れましたか?

于 2013-01-29T09:21:52.620 に答える
7

ORMを使用しているときに、リポジトリパターンの使用を拒否します。その場合、メリットはほとんどないと思います。(はい、私は熱狂者によって約2,000回投票されることを期待しています)。

EFを使用して、コンテキストのインターフェイスを作成します

public interface IDinnerContext : IDisposable
{
    IDbSet<Dinner> Dinners;

    int SaveChanges();
}

次に、このインターフェイスをEF DatabaseContextの実装とビオラに貼り付けます!どこでもEFを使用でき、MOCK実装を使用してdbアクセスを単体テストし、必要に応じてインジェクションを使用できます。600万のGetByXXXメソッドを使用する必要はありません。IQeryableはそれを処理し、実行が遅れます。IDBSetにはすでにAdd/Removeがあるため、Insert/Deleteメソッドは実際には必要ありません。私はより少ない抽象化でよりクリーンで読みやすいコードを持っています。

同じクエリが多くの異なる場所で使用されている場合があり、それを本当に一般的にしたい場合は、それをサポートするメカニズムを追加できます。ただし、95%の場合、クエリはビジネスロジックX(単純なGetByステートメント以外のもの)を担当するコンポーネントに固有です。ですから、それは問題ではないと思います。

誤解しないでください。ORMがかなり適切になるまで、リポジトリパターンを忠実に使用していました。ORMがある程度洗練されたレベルに達すると、リポジトリパターンは不要になる可能性があると感じ、それなしでプロジェクトを開始しました。やがて他のみんなもこの方向、あるいはかなり似たような方向に進むと思いますが、古い習慣がなくなるまでにはしばらく時間がかかります。(一部のMSサンプルにはまだlock(this)が含まれているため、lock(this)の使用を主張している開発者もいます)。

于 2013-01-31T20:51:22.290 に答える
2

これはリポジトリパターンであり、それ自体がEntity Frameworkで不要になります。DbContextこれは、がリポジトリと作業単位として同時に機能するためですが、モック可能ではありませんIDbContext。したがってDbContext、後でコンポーネントを簡単にテストできるように、薄いリポジトリラッパーを配置することになります。

ISessionセッションとセッションファクトリはインターフェイスであるため、NHibernateでリポジトリパターンを使用したことは一度もないことを言及する価値があると思いますISessionFactory

どこか(IRepository)でインターフェースによるリポジトリーを使用してそれを注入すると、モック/スタブによるテストがはるかに簡単になります。

public class DinnerOperation
{
    private readonly IDinnerRepository repository;

    public DinnerOperation(IDinnerRepository dinnerRepository)
    {
        repository = dinnerRepository;
    }
}

もちろん、適切なインスタンスを注入するには(DinnerRepositoryこの場合)、選択したIoCコンテナーを使用するか、「手動で」DIを実行する必要があります。

DinnerOperationそうすれば、モックまたはスタブされたリポジトリに対してクラスをテストできます。インスタンス化するときDbContext、できません。

于 2013-01-29T09:18:00.220 に答える