NHibernate 3.3正确加入QueryOver一对一关系

时间:2015-07-09 18:04:49

标签: c# nhibernate hql queryover

所以,情况就是这样。我有一个C#项目使用NHibernate 3.3(升级不是一个选项),具有以下类:

public class Person{
    public List<PersonAddress> PersonAddresses {get;set;}
}

public class NaturalPerson : Person{
    public NaturalProperty NaturalProperty {get;set;}
}

public class LegalPerson : Person{
    public LegalProperty LegalProperty {get;set;}
}

public class Quarantine{
    public Person QuarantinePerson {get;set;}
    public QuarantineProperty QuarantineProperty {get;set;}
}

我需要做的是获得可能或不“隔离”并且满足涉及隔离区财产以及法律或自然财产的不同条件的人员。基本上我需要的是人员的左连接,或隔离的正确加入:

Select *
From Quarantine q
Right Join Persons p on p.ID = q.QuarantinePersonID
Left Join NaturalPersons np on p.ID = np.ID
Left Join LegalPersons lp on p.ID = lp.ID
Where q.Property = 1
and np.Property = 1

这就是我现在所拥有的。我设法做了我需要的“from”条款,但是我遇到了“select”和“where”条款的严重问题:

Person p = null;
Quarantine q = null;
var results = this.Session.QueryOver<Quarantine>(() => q)
                  .JoinQueryOver<Person>(() => q.QuarantinePerson, () => p, JoinType.RightOuterJoin)
                  .SelectList(list => list
                     .Select(() => p.Id))
                  .TransformUsing(Transformers.AliasToBean<Person>())
                  .List<Person>();

此代码生成以下查询:

`SELECT p1_.PersonID as y0_
FROM   BUP.Quarantines this_
       right outer join BUP.Persons p1_
         on this_.QuarantinePersonID = p1_.PersonID
       left outer join BUP.LegalPersons p1_1_
         on p1_.PersonID = p1_1_.PersonID
       left outer join BUP.NaturalPersons p1_2_
         on p1_.PersonID = p1_2_.PersonID`

正如我所说,“来自”条款是可以的。现在问题在于Select和Where子句。

Select的主要问题是我需要整个Person对象,无论是法人还是自然人。我尝试从查询中删除.SelectList,但它抛出了一个PropertyNotFoundException:“找不到类'Person'中属性'p'的setter”。

Where子句的问题在于我不知道如何根据NaturalPerson和LegalPerson的属性添加条件。我在过滤Quarantine和Person属性方面没有问题,但还没有成功地对其他类做同样的事情。

此外,此查询应尽可能高效,因为超时是一个严重的问题。我已经设法用子查询等方法做了其他解决方案,但是花了太长时间。

任何有关这两个问题的帮助都将非常感谢!

谢谢!

1 个答案:

答案 0 :(得分:0)

您可以使用子查询 future 混合,在一行中执行两个查询:

var subquery = QueryOver.Of<Quarantine>()
    .Select(x => x.QuarantinePerson.Id);

var naturalPersons = Session.QueryOver<NaturalPerson>()
    .WithSubquery.WhereProperty(x => x.Id).NotIn(subquery)
    //.Where(x => x.NaturalProperty == somehing)
    .Future();

var legalPersons = Session.QueryOver<LegalPerson>()
    .WithSubquery.WhereProperty(x => x.Id).NotIn(subquery)
    //.Where(x => x.LegalProperty == somehing)
    .Future();

var persons = naturalPersons.Cast<Person>().Union(legalPersons);