LINQ to SQL Data Contextをラップするリポジトリクラスがあります。リポジトリクラスは、すべてのデータ層ロジック(およびキャッシュなど)を含むビジネスラインクラスです。
これが私のレポインターフェースのv1です。
public interface ILocationRepository
{
IList<Location> FindAll();
IList<Location> FindForState(State state);
IList<Location> FindForPostCode(string postCode);
}
ただし、FindAllのページングを処理するために、IListではなくIQueryable <ILocation>を公開してページングなどの状況でのインターフェイスを簡略化するかどうかを検討しています。
データリポジトリからIQueryableを公開することの長所と短所は何ですか?
どんな助けでも大歓迎です。
長所;構成可能性:
短所;非テスト性:
IQueryable<T>
構成可能であるため、構成不可能な実装を除外します-または、独自のクエリプロバイダーを作成するように強制します安定性のために、私はnotを公開してIQueryable<T>
またはExpression<...>
自分のリポジトリ。これは、リポジトリがどのように動作するかを知っており、上位層が「実際のリポジトリがこれをサポートしているか」を心配することなくモックを使用できることを意味します。 (統合テストの強制)。
私はまだIQueryable<T>
etcリポジトリの内部-境界を超えていない。私はいくつか投稿しました このテーマについてのより多くの考えはここにあります 。リポジトリー・インターフェースにページング・パラメーターを配置するのも同じくらい簡単です。 (インターフェースで)拡張メソッドを使用してoptionalページングパラメーターを追加することもできるので、具象クラスは実装するメソッドが1つだけですが、2つまたは3つのオーバーロードが利用できる場合があります発信者に。
前の回答で述べたように、IQueryableを公開すると、呼び出し元がIQueryable自体で遊ぶことができます。これは、危険になるか、危険になる可能性があります。
ビジネスロジックの最初の役割は、データベースの整合性を維持することです。
IListを公開し続けることができ、次のようにパラメーターを変更することができます。これが私たちのやり方です...
public interface ILocationRepository
{
IList<Location> FindAll(int start, int size);
IList<Location> FindForState(State state, int start, int size);
IList<Location> FindForPostCode(string postCode, int start, int size);
}
サイズ== -1の場合、すべてを返します...
別の方法...
それでもIQueryableを返したい場合は、関数内でListのIQueryableを返すことができます。たとえば...
public class MyRepository
{
IQueryable<Location> FindAll()
{
List<Location> myLocations = ....;
return myLocations.AsQueryable<Location>;
// here Query can only be applied on this
// subset, not directly to the database
}
}
最初の方法は、すべてではなく少ないデータを返すため、メモリよりも優れています。
IEnumerable
の代わりにIList
を使用することをお勧めします。これにより、柔軟性が向上します。
これにより、リポジトリで追加の作業を行わなくても、実際に使用するデータの部分のみをDbから取得できます。
// Repository
public interface IRepository
{
IEnumerable<Location> GetLocations();
}
// Controller
public ActionResult Locations(int? page)
{
return View(repository.GetLocations().AsPagination(page ?? 1, 10);
}
とてもきれいでシンプルです。