NHibernate で奇妙な N+1 選択の問題が発生しています。リンクされたプロパティの 1 つが null である一連のエンティティを要求するクエリを実行しています。この場合、正しいデータを選択するためだけに NHibernate によってリンクされたプロパティが返される必要はありません。
最初のエンティティは予約ウィンドウです
public class BookingWindow : Entity<BookingWindow>
{
// Blah blah blah
/// <summary>
/// Gets or sets the booking order item.
/// </summary>
/// <value>
/// The booking order item.
/// </value>
public virtual BookingWindowOrderItem BookingOrderItem { get; set; }
}
そして、次のような BookingWindowOrderItem
public class BookingWindowOrderItem : OrderItem
{
// Blah blah blah
public virtual BookingWindow BookingWindow { get; set; }
}
ここにそれぞれのマッピングがあります
public BookingWindowMap()
{
this.Schema("Customer");
this.Table("BookingWindows");
this.Id(x => x.Id).GeneratedBy.Guid();
this.Component(x => x.WindowPeriod, m =>
{
m.Map(x => x.Min, "StartTime");
m.Map(x => x.Max, "EndTime");
});
this.References(window => window.BookingOrderItem).PropertyRef("BookingWindow").Column("Id").LazyLoad().Nullable().ReadOnly();
this.Map(x => x.Price);
this.References(x => x.CustomerRoom).ForeignKey("RoomId").Column("RoomId");
}
と
public BookingWindowOrderItemMap()
{
this.DiscriminatorValue(1);
this.References(x => x.BookingWindow).LazyLoad().Column("OrderItemForeignId").ForeignKey("OrderItemForeignId");
}
次のクエリを実行すると、注文項目のない正しい予約ウィンドウが返されます。
Session.QueryOver<BookingWindow>().Where(w => w.CustomerRoom.Id == Guid.Parse(roomId)).Left.JoinQueryOver(bw => bw.BookingOrderItem).WhereRestrictionOn(item => item.Id).IsNull.List<BookingWindow>();
したがって、最初のクエリがデータベースに対して発行されます (注文項目の列が選択されているため、少し面倒ですが、実際の問題はすぐに発生します)。
this_.Id を Id2_1_ として、this_.Price を Price2_1_ として、this_.RoomId を RoomId2_1_ として、this_.StartTime を StartTime2_1_ として、this_.EndTime を EndTime2_1_ として、bookingwin1_.Id を Id4_0_ として、bookingwin1_.Price を Price4_0_ として、bookingwin1_.Description を Descript4_4_0_ として、bookingwin1_ として選択します。 OrderId4_0_ としての .OrderId、Bookingwin1_.OrderItemParentId として OrderIte6_4_0_、bookingwin1_.OrderItemForeignId として OrderIte7_4_0_ FROM Customer.BookingWindows this_ left 外部結合 Payment.OrderItem bookingwin1_ on this_.Id=bookingwin1_.OrderItemForeignId および bookingwin1_.OrderItemTypeId='1' WHERE this_.RoomId = ? そしてbookingwin1_.Idはnullです
しかし、返された予約ウィンドウごとに、リンクされた注文項目を要求していないか、必要としていないにもかかわらず、追加の選択があります。これはクエリ オーバー メソッド内で発生するため、返された予約ウィンドウを手動で反復処理することはありません。
Bookingwin0_.Id を Id4_0_ として、bookingwin0_.Price を Price4_0_ として、bookingwin0_.Description を Descript4_4_0_ として、bookingwin0_.OrderId を OrderId4_0_ として、bookingwin0_.OrderItemParentId を OrderIte6_4_0_ として、bookingwin0_.OrderItemForeignId を OrderIte7_4_0_ として選択します。そしてbookingwin0_.OrderItemTypeId='1'
ここで私が犯したエラーを誰かに説明してもらえますか。たぶんそれは明らかですが、私は数時間苦労し、忍耐力の終わりに:)