リポジトリパターンの実装についてたくさん読んだのですが、エンティティプロジェクションクエリを実装する方法がわかりません。
たとえば、大規模で複雑な製品エンティティがありますが、製品の名前とIDのみを表示したいと思います。このプロジェクションはどこに実装すればよいですか?私のエンティティリポジトリまたは呼び出し元コードにありますか?
リポジトリパターンの実装についてたくさん読んだのですが、エンティティプロジェクションクエリを実装する方法がわかりません。
たとえば、大規模で複雑な製品エンティティがありますが、製品の名前とIDのみを表示したいと思います。このプロジェクションはどこに実装すればよいですか?私のエンティティリポジトリまたは呼び出し元コードにありますか?
私はこれをリポジトリで行います。
たとえば、私のProductRepositoryインターフェイスは次のようになります。
interface IProductRepository
{
Product Get( int productId );
void Save( Product product );
ProductView FindProducts(string productNameSearch);
}
ProductView
の簡略化された表現はどこにありますかProduct
。(たとえば、名前とIDのみが含まれます)。
ProductViewを取得するためのプロジェクションは、抽象化する必要があるものであり、リポジトリはそのための良い場所です、imho。
私は最近、次のパターンを夢見ています。
interface IRepository
{
Product FindByName(string name);
ProjectionType FindByName<ProjectionType>(string name,
Expression<Func<Product, ProjectionType>> selector);
// ...
}
このパターンを使用すると、たとえば次のように、LINQ 式と匿名クラスを使用してオンザフライでプロジェクションを指定できます。
var productView = repository.FindByName("foo",
p => new { p.SomeProperty, p.SomeOtherProperty } );
これはかなりきれいだと思います。NHibernate.Linq を使用すると、実装は次のようになります。
ProjectionType FindByName<ProjectionType>(string name, Expression<Func<Product, ProjectionType>> selector)
{
using(var session = this.sessionFactory.OpenSession()) {
return session.Linq<Product>()
.Where(p => p.Name.Equals(name))
.Select(selector)
.SingleOrDefault();
}
}
免責事項: 上記のコードのバグや不適切なスタイルに注意してください。コンパイルさえできないかもしれません。これは私の頭の先からです。しかし、私はその考えはかなり明確であるべきだと思います。
何かご意見は?