私はこの流暢なNHibernateマッピングを持っています:
public LossMap()
{
Table("losses");
Id(x => x.Id).Column("id");
References(x => x.Policy).Column("pol_id");
HasMany(x => x.Statuses).KeyColumn("loss_id").Cascade.All().Inverse();
HasMany(x => x.Reserves).KeyColumn("loss_id").Cascade.All().Inverse();
HasMany(x => x.Payments).KeyColumn("loss_id").Cascade.All().Inverse();
}
public LossPaymentMap()
{
Table("losspayments");
Id(x => x.Id).Column("id");
Map(x => x.Type).Column("type_id");
References(x => x.Reserve).Column("reserve_id");
}
public LossReserveMap()
{
Table("lossreserves");
Id(x => x.Id).Column("id");
Map(x => x.Type).Column("type_id");
Map(x => x.Status).Column("status_id");
References(x => x.ParentReserve).Column("parent_reserve_id");
}
public LossStatusMap()
{
Table("lossstatuses");
Id(x => x.Id).Column("id");
Map(x => x.Status).Column("status_id");
Map(x => x.ExpirationDate).Column("expirationdate");
References(x => x.Loss).Column("loss_id");
}
要約する:
- 損失には多くの支払い、準備金、ステータスがあります
- 支払いには1つの予約があります
次の制約を使用して、損失とその支払いおよび準備金(ステータスではない)を取得しようとしています。
- 「status.Statusnotin(1,2,7)」のステータスが少なくとも1つある損失のみをフェッチします。
- Loss.Paymentsをフェッチするのは、「loss.Payment.Type = 2およびloss.Payment.Reserve.Status!= 4)」の場合のみです。
- Reserve.Status!=3の場合にのみLoss.Reservesをフェッチします
2つの並列関係を取得しようとしているので、ここで説明されているように、デカルト積を回避するためにマルチクエリまたは先物を使用する必要があります(右?):http://ayende.com/blog/4367/eagerly-loading-entity-associations- nhibernateで効率的に
私はこのクエリを(HQLで)思いついた:
int[] statuslist = new int[3] {1, 2, 7};
var losses =
session.CreateQuery(
"from Loss l left join fetch l.Payments as payment join l.Statuses as status where l.Policy.Product.Id = :tid1 " +
"and status.Status not in ( :statuslist1) " +
"and payment.Type = 2 and payment.Reserve.Status != 4")
.SetParameter("tid1", productid)
.SetParameterList("statuslist1", statuslist)
.Future<Loss>();
session.CreateQuery(
"from Loss l left join fetch l.Reserves as reserve join l.Statuses as status where l.Policy.Product.Id = :tid2 " +
"and status.Status not in ( :statuslist2) " +
"and reserve.Status != 3 ")
.SetParameter("tid2", productid)
.SetParameterList("statuslist2", statuslist)
.Future<Loss>();
var list = losses.ToList();
ただし、このクエリを実行すると、次のエラーが発生します。NHibernate.HibernateException:マルチクエリ[..SQLクエリ]の実行に失敗しました---> System.ArgumentException:値「System.Object[]」はタイプ「エンティティ」ではありません.Loss」であり、この汎用コレクションでは使用できません。
私がここで間違っていることの手がかりはありますか?
ステータス制約を削除すると、クエリは機能します。
var losses =
session.CreateQuery(
"from Loss l left join fetch l.Payments as payment where l.Policy.Product.Id = :tid1 " +
"and payment.Type = 2 and payment.Reserve.Status != 4")
.SetParameter("tid1", productid)
.Future<Loss>();
session.CreateQuery(
"from Loss l left join fetch l.Reserves as reserve where l.Policy.Product.Id = :tid2 " +
"and reserve.Status != 3 ")
.SetParameter("tid2", productid)
.Future<Loss>();
ただし、結果は私が望むものではありません(私はその制約が必要です)。
何かアドバイス ?
ああ、HQLの使用は「必須」ではありません。これが、LinqまたはQueryOverを使用して可能であれば、問題はありません。
ありがとう!