0

MVC 4 Web サイトを構築しており、リポジトリ パターンに従おうとしています。

以下のような複雑なセットアップを見てきましたが、スキル レベルが原因でそれを実行できません。

public interface IEntityRepository<T>
    where T : class, IEntity, new()
{
    void CommitChanges();
    void DeleteOnCommit(T entity);
    T GetEntity(int key);
    IQueryable<T> GetAll();
    int InsertOnCommit(T entity);
}

シンプルであるため、代わりにこのアプローチを選択しました。

public class EntityAdminRepository : IAdminRepository {

    AdminEntities db = new AdminEntities();

    public Models.Product CreateNewProduct(Models.Product productToCreate) {
       db.Products.Add(productToCreate);
       return productToCreate;
    }

    public void DeleteProduct(int id) {
        db.Products.Remove(GetProductByID(id));
    }

    public Models.Product GetProductByID(int id) {
        return db.Products.FirstOrDefault(d => d.ID == id);
    }

    public IEnumerable<Models.Product> GetAllProducts() {
        return db.Products;
    }

    public Models.Category CreateNewCategory(Models.Category categoryToCreate) {
        throw new NotImplementedException();
    }

    public void DeleteCategory(int id) {
        throw new NotImplementedException();
    }

    public Models.Category GetCategoryByID(int id) {
        throw new NotImplementedException();
    }

    public IEnumerable<Models.Category> GetAllCategories() {
        throw new NotImplementedException();
    }

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

アップスケーリングの問題(とにかく他の場所にあると思います)は別として、このソリューションは非常に恐ろしいので、今すぐ捨てて、最初の例を理解して実装できるようになるまで作業する必要がありますか?

更新 1: 最初のアプローチを使用する際の問題は、コントローラーでこの時点で終了する次の機能を再作成する方法がわからないことです。

    protected IAdminRepository _repository;

    public AdminController() : this(new EntityAdminRepository()) { }
    public AdminController(IAdminRepository repository) {
        _repository = repository;
    }

そして、この方法は、DTO ごとにエンティティがあることを意味します。これがどのようにまとめられるのでしょうか?

更新 2:

public class DatabaseRepository<T> : IRepository<T> 
    : where T:class, IEntity, new() 
{
    private DbContext context = new MyDbContext(); // proper data actions
    public T GetEntity(int id) 
    {
        return context.Tables<T>.FirstOrDefault(x => x.Id == id);
    }
}

public class InMemoryRepository<T> : IRepository<T> 
    : where T:class, IEntity, new() 
{
    private List<T> context = new List<T>(); // stuff for unit testing
    public T GetEntity(int id) 
    {
        return context.FirstOrDefault(x => x.Id == id);
    }
}
4

3 に答える 3

1

技術的には、モデルごとに1つのリポジトリがあります。各リポジトリは1つのモデルを処理し、モデルごとにインスタンス化する必要があります。ただし、最初の例では「ジェネリック」と呼ばれるものを使用しています。これは、C#やその他の.NETファミリ言語の優れた非常に強力な機能であり、コンパイラに基本的に次のように伝えることができます。有効なタイプ」。したがって、汎用リポジトリを使用すると、クラスは1つだけになりますが、渡された異なるモデルタイプを使用して、コード全体で複数回インスタンス化されます。

var catRepository = new Repository<Cat>();
var dogRepository = new Repository<Dog>();

CatRepositoryaやaなどを定義する代わりにDogRepository、無限に。

于 2013-03-07T19:29:23.923 に答える
1

私の経験では、プロジェクトの最後に到達したときに、どんなに一生懸命に努力し、どれだけ長く費やしても、[もう一度やり直すことができれば]それをどのように行ったかを常に知っています。デザインに加えることができる改善はたくさんありますが、実用的なスタンスを取る必要があります。あなたは今何ができますか?

私はあなたが行くにつれてそれを数回再起動することを視野に入れてあなたが持っているものから始めることをお勧めします...


汎用インターフェースは非常に柔軟です。この記事をお勧めします。保存して何度も読んでください;-)

.NETJunkie-クエリ/コマンド

于 2013-03-07T19:27:59.520 に答える
1

アプローチの長所と短所を次に示します。

プロ

  • 単純
  • わかりやすい
  • 明示的
  • 必要なことを行います
  • 簡単にテストできます

コン

  • 多数のモデル タイプがあると扱いにくい
  • 反復コードが多い
  • 継承やジェネリックなどを利用しない
  • すべてのリポジトリを個別に変更する必要があるため、新しい機能を追加することは本質的に危険です。

そうは言っても、一般的なリポジトリは、全体的なニーズにより適している傾向があります。仕組みは次のとおりです。

まずはインターフェース。これは、それを実装するすべてのクラスが従うことを保証する、共通に合意された契約を定義するため、重要です。

<T>、インターフェイスがジェネリック型として宣言されていることを意味します。ジェネリック型は、基本的にコードを「テンプレート化」して繰り返しを避けることができるため、便利です (DRY!)。はT、実際の型名がコードで実際に使用されるときに置き換えられるプレースホルダー パラメーターです。

where T : class, IEntity, new()あなたがそれに慣れていないなら、ちょっとしたことです。このインターフェイスのようなジェネリック型は、制約が必要な場合があります。多くの場合、anyTが参照型であることを保証する必要があります。の後のすべてが:まさにそのような制約セットを構成します。の値は値型ではなく、クラスでなければならないことclassを意味します。のすべてのクラスがコントラクトを実装する必要があることを意味します。は最も直感的ではなく、既定のパラメーターなしのコンストラクターが必要であることを意味します。多くの場合、単に を呼び出すことができるようにしたいため、これは重要です。 TIEntityTIEntitynew()Tvar a = new T()

これが例です

public interface IEntity { public int Id { get; set;} }

public class FooEntity : IEntity { public int Id { get; set; } }

public class Repository<T> : IRepository<T> 
    : where T:class, IEntity, new() 
{
    private DbContext context = new MyDbContext(); // or however your db store works

    public Repository(IDbContext ctx) { context = ctx; }

    public T GetEntity(int id) 
    {
        return context.Tables<T>.FirstOrDefault(x => x.Id == id);
    }
}

私がまだその<T>ようなものをどのように使用しているかに注意してください。それが特製ソースです。ProductRepositoryこれは、次のように my を使用できることを意味します。

var a = new Repository<Product>();
var foo = a.GetByKey(1234); //foo is Product

これで、リポジトリを使用してオブジェクトを操作および変更するには、次の簡単な方法があります。

1) リポジトリから変更するオブジェクトを取得します 2) オブジェクトに変更を加えます 3) 変更をデータストアに書き込むようにリポジトリに指示します

コードでは、

var a = new Repository<Product>(/* optionally, a mocked context object */);
var foo = a.GetByKey(1234); //foo is Product
// modify
foo.Name = "Bleach";
a.CommitChanges();
// create
var bar = new Product();
bar.Name = "Paper Towels";
a.InsertOnSubmit(bar);
a.CommitChanges();

更新された投稿のコントローラーの例を想定して、MVC の例を次に示します。

// ctor not listed here

public ActionResult AddProduct(Product product)
{
    if (Model.IsValid) // validate the model - may not be exact syntax...
    {
        _repository.InsertOnSubmit(product);
        _repository.CommitChanges();

        return View(product);
    }
    else { //do something else }
}
于 2013-03-07T19:24:48.667 に答える