NHibernate-通过期货获取

NHibernate-通过期货获取,hibernate,nhibernate,fluent-nhibernate,hql,nhibernate-criteria,Hibernate,Nhibernate,Fluent Nhibernate,Hql,Nhibernate Criteria,我有一个流畅的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.Res

我有一个流畅的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,2,7)”中
  • 仅在“Loss.Payment.Type=2和Loss.Payment.Reserve.Status!=4”的情况下提取Loss.Payments
  • 仅获取丢失。保留,其中保留。状态!=三,
  • 当我试图获取2个并行关系时,我必须使用多重查询或期货来避免笛卡尔积(对吗?),如下所述:

    我提出了这个查询(在HQL中):

    int[]statuslist=newint[3]{1,2,7};
    风险价值损失=
    session.CreateQuery(
    “从Loss l left加入获取l.付款作为付款加入l.状态作为状态,其中l.Policy.Product.Id=:tid1”+
    “和状态。状态不在(:statuslist1)”+
    “和payment.Type=2和payment.Reserve.Status!=4”)
    .SetParameter(“tid1”,productid)
    .SetParameterList(“状态列表1”,状态列表)
    .Future();
    session.CreateQuery(
    “从丢失l左连接获取l.保留作为保留连接l.状态作为状态,其中l.Policy.Product.Id=:tid2”+
    “和状态。状态不在(:statuslist2)”+
    “和保留状态!=3”)
    .SetParameter(“tid2”,产品ID)
    .SetParameterList(“状态列表2”,状态列表)
    .Future();
    var列表=损失。ToList();
    
    但是,在执行此查询时,我收到一个错误:NHibernate.HibernateException:未能执行多查询[…SQL query]-->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>();
    
    var损失=
    session.CreateQuery(
    “从Loss l left加入fetch l.Payments作为付款,其中l.Policy.Product.Id=:tid1”+
    “和payment.Type=2和payment.Reserve.Status!=4”)
    .SetParameter(“tid1”,productid)
    .Future();
    session.CreateQuery(
    “从丢失l左连接获取l.保留作为保留,其中l.Policy.Product.Id=:tid2”+
    “和保留状态!=3”)
    .SetParameter(“tid2”,产品ID)
    .Future();
    
    然而,结果不是我想要的(我需要那个约束)

    有什么建议吗

    哦,使用HQL不是“必须的”,如果可以使用Linq或QueryOver,我对此没有问题


    谢谢

    我不倾向于使用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)));
    
    int[]值=新的int[]{1,2,3};
    var query1=session.CreateCriteria()
    .CreateAlias(“Status”,“s”).Add(Expression.Not(Expression.In(“s.Status”,values)))
    .CreateAlias(“Reserves”,“r”,JoinType.LeftOuterJoin,Expression.Not(Expression.Eq(“r.Status”,3)));
    
    储备关联的标准将添加到左侧外部联接子句中,这意味着只有该关系应用了过滤器

    对于第二个查询,您需要类似的东西,但我不确定您是否可以将来自另一个表的约束放在左侧外部联接中(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));
    
    detachedCriterias paymentSubQuery=null//查询获取类型为2和保留的所有付款。状态!=4.
    var query2=session.CreateCriteria()
    .CreateAlias(“Status”,“s”).Add(Expression.Not(Expression.In(“s.Status”,values)))
    .CreateAlias(“Payments”,“p”,JoinType.LeftOuterJoin).Add(subquerys.PropertyIn(“p.Id”,paymentSubQuery));
    

    我没有实际运行这些,但我认为这应该大致满足您的需要。

    您有一个连接,但没有指定您想要的对象,因此您实际上得到了一个元组

    您应该在选择中指定所需的实体/属性,例如:

    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.distinctroventy

    对于IQuery/ICriteria:
    .SetResultTransformer(Transformers.distinctrumentity)


    查询版本:
    .TransformUsing(Transformers.distinctroventy)

    有没有办法使用NHibernate LINQ api进行相同类型的投影?我不使用LINQ,所以我不确定,尽管这似乎是您想要的
    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