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:
I am trying to fetch Losses and their payments and reserves (but not statuses) with the following constraints:
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!
You have a join but have not specified which object you want thus you're actually getting back a tuple.
You should specify which entities/properties you want in the select, eg:
select l
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
You should also note that when using a join you can get multiple results for the same entity, if you only want unique entities you should use Transformers.DistinctRootEntity
For IQuery/ICriteria: .SetResultTransformer(Transformers.DistinctRootEntity)
For QueryOver: .TransformUsing(Transformers.DistinctRootEntity)