我有这个Fluent 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");
}
总结:
我试图通过以下限制来获取损失及其付款和储备(但不是状态):
当我试图获取2个并行关系时,我必须使用多个查询或期货来避免笛卡尔积(对吗?),如下所述:http://ayende.com/blog/4367/eagerly-loading-entity-associations-efficiently-with-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查询] ---&gt; System.ArgumentException:值“System.Object []”不是“Entities.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,我没有问题。
谢谢!
答案 0 :(得分:1)
你有一个连接,但是没有指定你想要的对象,因此你实际上已经取回了一个元组。
您应该在select中指定所需的实体/属性,例如:
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
您还应注意,使用联接时,您可以为同一实体获得多个结果,如果您只想要使用Transformers.DistinctRootEntity
对于IQuery / ICriteria:.SetResultTransformer(Transformers.DistinctRootEntity)
对于QueryOver:.TransformUsing(Transformers.DistinctRootEntity)
答案 1 :(得分:0)
我不倾向于使用HQL,所以不能真正建议,但我不确定上面的查询是否正是你想要的。无论子对象的标准如何,您是否想要获取所有损失?上面的查询仅返回符合子对象上设置的条件的损失。看起来你想要返回符合主要标准的所有损失,但过滤那些儿童收藏品?我的意思是,根据当前查询,如果您有一个状态为2但没有支付类型为2的付款,那么将不会从查询中返回损失实体。相反,我认为您需要在连接上应用过滤器,以便从查询返回损失实体,但付款集合为空。例如,第一个查询的内容如下:
int[] values = new int[] { 1,2,3};
var query1 = session.CreateCriteria<Trade>()
.CreateAlias("Status", "s").Add(Expression.Not(Expression.In("s.Status", values)))
.CreateAlias("Reserves", "r", JoinType.LeftOuterJoin, Expression.Not(Expression.Eq("r.Status", 3)));
Reserves关联的条件将被添加到左外连接子句中,这意味着只有该关系应用了过滤器。
对于第二个查询,您需要类似的东西,但我不确定您是否可以从左外连接中的另一个表中放置约束(Payment.Reserve.Status!= 4)。为此,您可以使用子查询。类似的东西:
DetachedCriteria paymentSubQuery = null; //make a query for getting all payments with type 2 and reserve.Status != 4
var query2 = session.CreateCriteria<Trade>()
.CreateAlias("Status", "s").Add(Expression.Not(Expression.In("s.Status", values)))
.CreateAlias("Payments", "p", JoinType.LeftOuterJoin).Add(Subqueries.PropertyIn("p.Id", paymentSubQuery));
我实际上没有运行这些,但我认为应该大致给你你想要的东西。