I have this Fluent NHibernate mapping:
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"); } To summarize:
- Loss has many Payments, Reserves and Statuses
- Payment has one Reserve
I am trying to fetch Losses and their payments and reserves (but not statuses) with the following constraints:
- Only fetch Losses which have at least one status with "status.Status not in (1,2,7)".
- Only fetch Loss.Payments where "loss.Payment.Type = 2 and loss.Payment.Reserve.Status != 4)"
- Only fetch Loss.Reserves where Reserve.Status != 3
As I am trying to fetch 2 parallel relations, I have to use multiqueries or futures to avoid Cartesian product (right?), as explained here: http://ayende.com/blog/4367/eagerly-loading-entity-associations-efficiently-with-nhibernate
I came up with this query (in 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(); However, when executing this query, I get an error: NHibernate.HibernateException: Failed to execute multi query[..SQL query]---> System.ArgumentException: The value "System.Object[]" is not of type "Entities.Loss" and cannot be used in this generic collection.
Any clues what am I doing wrong here ?
When I remove the status constraint, the query works:
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>(); However, the results are not what I want (I need that constraint).
Any advice ?
Oh, and using HQL is not a "must-be", if this is possible using Linq or QueryOver, I've got not problem with that.
Thanks!