使用QueryOver,如何根据方法参数有条件地过滤结果?

时间:2015-03-17 19:31:58

标签: c# nhibernate

对于我正在研究的项目,我最近一直在使用NHibernate中的QueryOver语法,而且我遇到了一些问题,我没有找到任何关于如何解决的文本。 / p>

在我正在进行的项目中,我有一个存储库方法,可以将一组人员分配到项目中。存储库方法如下所示(当前非功能性代码)

public static IEnumerable<ProjectAssignment> GetProjectAssignments(int projectId, bool includeAlternates)
{
    using (ISession session = DataContext.GetSession())
    {
        List<ProjectAssignment> results = session
            .QueryOver<ProjectAssignment>()
            .Where(p => p.ProjectId == projectId)
                // Problem statement!
                .And(p => includeAlternates || !p.IsAlternate)
            .List().ToList();

        return results;
    }
}

我的ProjectAssignment类和它的映射一样不重要,因为根据我今天早些时候提出的一个问题,问题很明显:includeAlternates布尔值没有映射到我的ProjectAssignment类也不应该;这是函数的一个参数。

我想问的是:

Query all Project Assignments
    Where the project ID is the one I want
    And if alternate assignments are included, just include the assignment, 
        otherwise only include the assignment if it's not an alternate assignment
    And return that list from the query.

为了做到这一点,I've been made aware of something called a Projection,NHibernate的一个新概念。但是,在阅读了其他一些问题后,我非常,非常,非常在两个关键点上不清楚,并且试图找到官方文档并没有帮助,因为它是以我完全找到的方式编写的不透明:

  • 究竟是什么投影?一位消息人士称,“它就像是SQL中的SELECT语句”。另一个人把它比作LINQ .Select()调用,它实际上只是进行转换。据我所知,这些是两个完全不同的东西,因此其中一个来源必定是错误的。
  • 回到我的具体编码问题的主题 - 如何在这些问题之上完成那个伪代码 - 我能以什么方式实际解决我的问题?

所以,我的问题:

  • 究竟什么是NHibernate中的投影?
  • 以何种方式可以实现上面给出的伪代码块中所述的条件行为?

2 个答案:

答案 0 :(得分:4)

NHibernate将尝试在您的条件中解析SQL所包含的内容,并且将无法在您的映射中解析它,或者在该上下文中对解析器没有意义,这可能是您的错误&#39重新体验 对于NHibernate,预测并不是一个新概念,但我不知道它们与你当前的情况有什么关系。

您的代码应该读取更类似于下面的内容,其中您将条件包含在QueryOver中或不基于布尔值:

public static IEnumerable<ProjectAssignment> GetProjectAssignments(int projectId, bool includeAlternates)
{
    using (ISession session = DataContext.GetSession())
    {
        var query = session.QueryOver<ProjectAssignment>()
                       .Where(p => p.ProjectId == projectId);

        if (!includeAlternates) 
        {
            query.And(p => !p.IsAlternate);
        }

        List<ProjectAssignment> results = query.List().ToList();
        return results;
    }
}

答案 1 :(得分:1)

  

究竟什么是投影?一位消息人士称,“它就像SQL中的SELECT语句”。另一个人把它比作LINQ .Select()调用,它实际上只是进行转换。就我所知,这是完全不同的两件事,所以其中一个来源必定是错误的。

我认为在您的其他问题的上下文中,评论指的是NHibernate NHibernate.Criterion.Projections类。这堂课&#39;成员可以与QueryOver或Criteria查询一起使用,以最终从使用NHibernate映射的实体生成SQL。

以下是使用Criteria API和Projections.Property方法的示例:

session.CreateCriteria(typeof(Person))
    .SetProjection(
        Projections.Property("FirstName"))
    .List<string>();

由于QueryOver是在Criteria API之上构建的,因此您仍然可以进入&#34; QueryOver不支持您出于某种原因尝试执行的操作时Projections.*方法。你的上一个问题包含了一个很好的例子;执行以下操作无法使用QueryOver:

session.QueryOver<Person>()
    .Select(p => p.LastName + ", " + p.FirstName)
        .List<string>();

然而,这将:

session.QueryOver<Person>()
    .Select(Projections.SqlFunction(
        "concat",
        NHibernateUtil.String,
        Projections.Property<Person>(p => p.LastName),
        Projections.Constant(", "),
        Projections.Property<Person>(p => p.FirstName)))
    .List<string>();

使用预测往往更冗长,但更强大。您应该能够使用具有各种Projections方法的表达式,从而无需字符串。

弗雷迪的回答解决了真正的问题,所以我将从答案中省略这一部分。