NHibernate Join Query with only one instance of QueryOver and no mapping relation defined

NHibernate Join Query with only one instance of QueryOver and no mapping relation defined

就我而言,我只有一个特定的存储库。让我们说“StudentRepository”。这个存储库对我隐藏了 ISession 实例,我唯一拥有的是 IQueryOver< Student,Student> 实例。 考虑以下实体与 NHibernate 的简单映射。

class Student
{
    public int Id {get;set;}
    public string Number  {get;set;}
}

class Exam{
    public int Id {get;set;}
    public double Score {get;set;}
    public string StudentNumber {get;set;}
}

你是对的,基本方法只是将真实关系添加到考试 class,例如:

public Student Student {get; set;}

不幸的是,这也不是一个选择

问题:我需要在 studentRepository 的考试实体上使用 "Score>70" 等条件进行查询。我如何在不知道会话并且没有在映射上定义关系的情况下使用 Nhibernate 生成这样的查询。 ?

所以我认为这里的主要问题是:要使用 QueryOver 连接到不相关的实体,需要将别名定义为根查询的变量(您的 QueryOver 用于学生)。 NHibernate QueryOver to join unrelated entities

中解释了如何进行此类联接

因此,如果您可以修改存储库 class 以允许为此 QueryOver 提供可选的别名变量,那将是最好的解决方案。类似这样的东西(我假设您使用的是 NHibernate 5.1 或更高版本):

Student studentAlias = null;
var studentsQueryOver= yourRepository.GetQueryOver<Student>(studentAlias);

Exam examAlias = null;

var students = studentsQueryOver
.JoinEntityAlias(() => examAlias, () => examAlias.StudentNumber == studentAlias.Number)
.Where(s => examAlias.Score > 70)
.List();

如果这不是一个选项,您仍然可以创建与不相关实体的连接,但您需要直接使用底层根 Criteria 构建它们。像这样:

Exam examAlias = null;

studentsQueryOver.RootCriteria
.CreateEntityAlias(
        nameof(examAlias),
        Restrictions.EqProperty("examAlias.StudentNumber", studentsQueryOver.RootCriteria.Alias + ".Number"),
        JoinType.LeftOuterJoin,
        typeof(Exam).FullName);

var students = studentsQueryOver
.Where(s => examAlias.Score > 70)
.List();

在 5.1 之前的 NHibernate 版本上,您可以使用子查询:

var subQuery = QueryOver.Of<Exam>()
    .Where(e => e.Score > 70)
    .Select(e => e.StudentNumber);

subQuery.RootCriteria.Add(Restrictions.EqProperty("StudentNumber", studentsQueryOver.RootCriteria.Alias + ".Number"))

//Or if root query alias variable available simply
//subQuery.And(e => e.StudentNumber == studentAlias.Number)

var students = studentsQueryOver
    .WithSubquery.WhereExists(subQuery)
    .List();