通常、UnitOfWorkはこの抽象化を提供します。変更する必要がある1つの場所であり、リポジトリはインターフェイスを介してそれに依存します。O / RMを変更する必要がある場合は、新しいUoWを実装するだけです。完了しました。
ところで、O / RMを切り替えるだけでなく、単体テストを考えてください。UnitOfWorkの実装は3つあります。1つはEF、1つはNH(実際には、Oracleサポートを必要とするクライアントのプロジェクト中にO / RMを切り替える必要があるため)、および1つはInMemoryの永続化です。InMemoryの永続性は、単体テストや、データベースを配置する準備が整う前のラピッドプロトタイピングにも最適でした。
フレームワークの実装は簡単です。最初に、一般的なIRepositoryインターフェイスがあります
public interface IRepository<T>
where T:class
{
IQueryable<T> FindBy(Expression<Func<T,Bool>>filter);
IQueryable<T> GetAll();
T FindSingle(Expression<Func<T,Bool>> filter);
void Add(T item);
void Remove(T item);
}
IUnitOfWorkインターフェース
public interface IUnitOfWork
{
IQueryable<T> GetSet<T>();
void Save();
void Add<T>(T item) where T:class;
void Remove<T>(T item) where T:class;
}
次はベースリポジトリです(抽象的かどうかの選択)
public abstract class RepositoryBase<T>:IRepository<T>
where T:class
{
protected readonly IUnitOfWork _uow;
protected RepositoryBase(IUnitOfWork uow)
{
_uow=uow;
}
public IQueryable<T> FindBy(Expression<Func<T,Bool>>filter)
{
return _uow.GetSet<T>().Where(filter);
}
public IQueryable<T> GetAll()
{
return _uow.GetSet<T>();
}
public T FindSingle(Expression<Func<T,Bool>> filter)
{
return _uow.GetSet<T>().SingleOrDefault(filter);
}
public void Add(T item)
{
return _uow.Add(item);
}
public void Remove(T item)
{
return _uow.Remove(item);
}
}
IUnitOfWorkの実装は、EF、NH、およびIn Memoryの子供の遊びです。私がIQueryableを返す理由は、同じ理由で、Ayendeが彼の投稿で述べたように、クライアントはLINQを使用して結果をさらにフィルター、ソート、グループ化、さらには投影することができ、それでもサーバー側で行われているすべての利点を得ることができます。