2つの同様の質問が見つかりました。
このページ によると:
複数のコレクションプロパティを同時に積極的にフェッチしないように注意してください。このステートメントはうまくいきますが:
var employees = session.Query<Employee>() .Fetch(e => e.Subordinates) .Fetch(e => e.Orders).ToList();
データベースに対してデカルト積クエリを実行するため、返される行の合計数は、下位の合計に注文の合計を掛けたものになります。
私が次のモデルを持っているとしましょう:
public class Person
{
public virtual int Id { get; private set; }
public virtual ICollection<Book> Books { get; set; }
public virtual ICollection<Article> Articles { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
}
QueryOver/Linqを使用して(デカルト積を返さずに)すべての人に本、記事、住所を積極的にロードする最も簡単な方法は何ですか?
ありがとう
更新:
以下の cremor の answer と Florian Lim の answerthis thread を参照してください。次のコードは適切に機能し、データベースへのラウンドトリップは1回だけです。
var persons = session.QueryOver<Person>()
.Future<Person>();
var persons2 = session.QueryOver<Person>()
.Fetch(x => x.Books).Eager
.Future<Person>();
var persons3 = session.QueryOver<Person>()
.Fetch(x => x.Articles).Eager
.Future<Person>();
var persons4 = session.QueryOver<Person>()
.Fetch(x => x.Addresses).Eager
.Future<Person>();
特に新しいバージョンのnhibernate(> = 4.0)を使用している場合は、可能な限りlinqプロバイダーを使用することをお勧めします。コレクションをISetsとしてマップしている限り(.netフレームワーク> = 4が必要)、これを変換して、熱心なロードを実行し、デカルト積を回避できるようにしました。これはあまり宣伝されていないような気がしますが、私はこの方法を他の何よりも適切に適用することを好みます:
public class Person
{
public virtual int Id { get; private set; }
public virtual ISet<Book> Books { get; set; }
public virtual ISet<Article> Articles { get; set; }
public virtual ISet<Address> Addresses { get; set; }
}
public Person()
{
this.Books = new HashSet<Book>();
this.Articles = new HashSet<Article>();
this.Addresses = new HashSet<Address>();
}
上記のようにコレクションを定義している場合は、次の操作を実行しても、デカルト積の問題を回避できます。
var persons = session.Query<Person>()
.FetchMany(x => x.Books)
.FetchMany(x => x.Articles)
.FetchMany(x => x.Addresses)
.ToList();