まず、いくつかの回答で示唆されているように、EF 自体はリポジトリ パターンです。リポジトリとして名前を付けるためだけに、さらに抽象化を作成する必要はありません。
単体テスト用のモック可能なリポジトリ、本当に必要ですか?
単体テストで EF がテスト DB と通信して、ビジネス ロジックを SQL テスト DB に対して直接テストできるようにします。リポジトリパターンをモックするメリットはまったくありません。テスト データベースに対して単体テストを実行する際に実際に間違っていることは何ですか? 一括操作ができないので、生の SQL を書くことになります。メモリ内の SQLite は、実際のデータベースに対して単体テストを実行するのに最適な候補です。
不必要な抽象化
将来、EF を NHbibernate などに簡単に置き換えることができるように、リポジトリを作成しますか? 素晴らしいプランに思えますが、本当に費用対効果が高いのでしょうか?
Linq は単体テストを殺しますか?
それがどのように殺すことができるかについての例を見たいと思います。
依存性注入、IoC
うわー、これらは素晴らしい言葉です。確かに理論的には素晴らしいように見えますが、優れたデザインと優れたソリューションの間でトレードオフを選択する必要がある場合があります。私たちはそれらすべてを使用しましたが、最終的にはすべてをゴミ箱に捨てて、別のアプローチを選択しました。サイズ vs スピード (コードのサイズと開発のスピード) は、実生活において非常に重要です。ユーザーは柔軟性を必要とし、DI や IoC の観点からコードの設計が優れているかどうかは気にしません。
Visual Studio をビルドしていない場合
Visual Studio や Eclipse のような複雑なプログラムを構築する場合、これらの優れた設計はすべて、多くの人によって開発され、高度にカスタマイズ可能である必要がある場合に必要です。これらの IDE は何年にもわたる開発を経て、すべての優れた開発パターンが具体化され、これらすべての優れた設計パターンが非常に重要な場所で進化してきました。しかし、単純な Web ベースの給与計算や単純なビジネス アプリを実行している場合は、数百万のユーザー向けに展開するだけの数百万のユーザー向けに時間をかけて構築するよりも、時間をかけて開発を進化させる方がよいでしょう。
フィルター ビューとしてのリポジトリ - ISecureRepository
一方、リポジトリは、現在のユーザー/ロールに基づいて必要なフィラーを適用することにより、データへのアクセスを保護する EF のフィルター処理されたビューである必要があります。
しかし、そうすると、管理するコードベースが膨大になるため、リポジトリはさらに複雑になります。人々は、さまざまなユーザー タイプまたはエンティティ タイプの組み合わせに対して、さまざまなリポジトリを作成することになります。これだけでなく、多くの DTO が発生します。
次の回答は、クラスとメソッドのセット全体を作成せずに Filtered Repository を実装した例です。質問に直接答えることはできませんが、質問を導き出すのに役立ちます。
免責事項: 私は Entity REST SDK の作成者です。
http://entityrestsdk.codeplex.com
上記を念頭に置いて、CRUD 操作のフィルターを保持する SecurityContext に基づいて、フィルター処理されたビューのリポジトリを作成する SDK を開発しました。また、複雑な操作を単純化するのは 2 種類のルールだけです。1 つはエンティティへのアクセス、もう 1 つはプロパティの読み取り/書き込みルールです。
利点は、さまざまなユーザー タイプに合わせてビジネス ロジックやリポジトリを書き直す必要がなく、単純にアクセスをブロックまたは許可することです。
public class DefaultSecurityContext : BaseSecurityContext {
public static DefaultSecurityContext Instance = new DefaultSecurityContext();
// UserID for currently logged in User
public static long UserID{
get{
return long.Parse( HttpContext.Current.User.Identity.Name );
}
}
public DefaultSecurityContext(){
}
protected override void OnCreate(){
// User can access his own Account only
var acc = CreateRules<Account>();
acc.SetRead( y => x=> x.AccountID == UserID ) ;
acc.SetWrite( y => x=> x.AccountID == UserID );
// User can only modify AccountName and EmailAddress fields
acc.SetProperties( SecurityRules.ReadWrite,
x => x.AccountName,
x => x.EmailAddress);
// User can read AccountType field
acc.SetProperties<Account>( SecurityRules.Read,
x => x.AccountType);
// User can access his own Orders only
var order = CreateRules<Order>();
order.SetRead( y => x => x.CustomerID == UserID );
// User can modify Order only if OrderStatus is not complete
order.SetWrite( y => x => x.CustomerID == UserID
&& x.OrderStatus != "Complete" );
// User can only modify OrderNotes and OrderStatus
order.SetProperties( SecurityRules.ReadWrite,
x => x.OrderNotes,
x => x.OrderStatus );
// User can not delete orders
order.SetDelete(order.NotSupportedRule);
}
}
これらの LINQ ルールは、操作ごとに SaveChanges メソッドでデータベースに対して評価され、これらのルールはデータベースの前でファイアウォールとして機能します。