ASP.NET MVC プログラムで同様のアプローチを使用していますが、これまでのところ非常にうまく機能しています。
私のIUnitOfWork
インターフェースは次のようになります。
public interface IUnitOfWork
{
IRepository<TEntity> GetRepositoryFor<TEntity>() where TEntity : class;
void SaveChanges();
}
関連するIRepository
インターフェイスは次のようになります。
public interface IRepository<TEntity> : IQueryable<TEntity> where TEntity : class
{
TEntity Find(params object[] keyValues);
void Insert(TEntity entity);
void Update(TEntity entity);
void Delete(TEntity entity);
}
そして、次のようにサービスに渡します。
public abstract class BaseService
{
public BaseService(IUnitOfWork unitOfWork)
{
// etc...
}
}
これにより、サービスがリポジトリをコンストラクターに個別に渡すことなく簡単に解決できるようになります。これは、単一のサービスで複数のリポジトリを操作する場合に役立ちます (例: 発注書と製品)。
このような ORM に依存しないインターフェイスを使用する利点の 1 つは、ORM を簡単に切り替えることができることです。正直に言うと、Entity Framework から別の ORM に変更する可能性はほとんどありませんが、実際には必要に応じて変更できます。おまけとして、私のサービスはテストがはるかに簡単で、使用中の ORM をまったく認識せず、上記の 2 つのインターフェースに対して完全に機能するため、これによりサービス クラスがよりクリーンになります。
一般的なリポジトリ インターフェースに関するコメントに関して、私のアドバイスは、実用的であり、あなたとあなたのアプリケーションにとって最適なことを行うことです。このまさにこのトピックに関する Stackoverflow に関する多くの質問があり、それらに対する答えは、どちらが最善の方法であるかについて大きく異なります (EG 公開IQueryable
vs IEnumerable
、ジェネリック vs 非ジェネリック)。
私のインターフェースがIRepository
; IDbSet
私がこの方法を選んだ理由は、 EGで行う Entity Framework エンティティ状態管理のすべてを実装で処理できるようにするためです。DbContext
public void Delete(TEntity entity)
{
if (Context.Entry(entity).State == EntityState.Detached)
{
EntitySet.Attach(entity);
}
EntitySet.Remove(entity);
}
これを使用した場合、サービス レイヤーでこれを実行する必要があり、汎用リポジトリよりもはるかに漏れやすい抽象化に見えるIDbSet
依存関係が必要になります。DbContext