私の ASP.NET MVC 4 プロジェクトでは、Repository と Unit Of Work を実装するこの例の設計原則に注意深く従っています。
私は、汎用リポジトリを示した後に書かれた記事に関する次のコメントに特に興味があります。
この汎用リポジトリは、典型的な CRUD 要件を処理します。より複雑なフィルタリングや順序付けなど、特定のエンティティ タイプに特別な要件がある場合は、そのタイプの追加メソッドを持つ派生クラスを作成できます。
私のアプリはその特定のケースを満たしているので、これをやろうとしました。記事と同じように GenericRepository と SharedContext クラスを作成しました (SharedContext は記事の UnitOfWork クラスとまったく同じですが、この名前の方が私にはわかりやすいです)。
汎用リポジトリ:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace BusinessLogicLayer.Repositories
{
public class GenericRepository<T> where T: class
{
internal DbSet<T> _dbSet;
internal DBConnection _context;
#region constructors
public GenericRepository(SharedContext ctx)
{
_context = ctx.Context;
}
public GenericRepository(DBConnection context)
{
_context = context;
_dbSet = context.Set<T>();
}
#endregion
}
}
SharedContext (作業単位) クラス:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BusinessLogicLayer.Repositories
{
public class SharedContext : IDisposable
{
#region repositories
private GenericRepository<Entities.Customer> _customerRepository;
/// <summary>
/// access the Customer entity
/// </summary>
public GenericRepository<Entities.Customer> CustomerRepository
{
get
{
if (_customerRepository == null)
_customerRepository = new GenericRepository<Entities.Customer>(_context);
return _customerRepository;
}
}
#endregion
#region context management
private Entities.DBConnection _context = new Entities.DBConnection();
internal Entities.DBConnection Context { get { return _context; } }
//other methods - save, delete
#endregion
}
}
ここに問題があります。上記の Context プロパティをどのように公開したかに注意してください。これが実際に意図されているかどうかは疑問です。それを行うことでパターンを壊しているように感じます。すべてが同じコンテキストでリポジトリを介して制御されるという考えが非常に気に入っていますが、汎用リポジトリでは提供されていないメソッドがいくつか必要なので、別の CustomerRepository を作成しました。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
namespace BusinessLogicLayer.Repositories
{
public class CustomerRepository: GenericRepository<Entities.Customer>
{
public CustomerRepository(SharedContext ctx)
: base(ctx)
{ }
public decimal GetCustomerBonusByFrequency()
{
//
}
}
}
...私のコントローラークラスでは、次のように使用します。
private SharedContext ctx = new SharedContext();
public PartialViewResult CustomerBonus()
{
CustomerRepository cRepo = new CustomerRepository(ctx);
var bonus = cRepo.GetCustomerBonusByFrequency();
return PartialView(bonus);
}
だから私の2つの質問は次のとおりです。
リスト項目
これは、記事で言及されている追加機能を追加するための意図された方法ですか? クラス CustomRepository を参照しています。これは、GenericRepository (もう使用していない) を介して Customer を取得する方法が既に存在していたため、パターンが壊れているように感じます。さらに、コンテキストを公開しています。
これが悪い場合、どうすれば正しく行うことができますか? 必要なのは、Customer エンティティに追加のメソッドを用意することだけですが、パターンを尊重する方法で行います。
どうも、
編集:
GenericRepository (SharedContext を受け取る) のコンストラクターと CustomerRepository クラスの :base(ctx) を削除すると、次のようになるため、SharedContext で Context プロパティを公開する必要がありました。
BusinessLogicLayer.DBModel.Customer には、0 引数を取るコンストラクターが含まれていません