【问题标题】:NHibernate / QueryOver: How to left join with parameterNHibernate / QueryOver:如何使用参数左连接
【发布时间】:2014-11-13 08:40:11
【问题描述】:

NHibernate / QueryOver API 中是否有办法传递映射中已有的参数(因此它使用该参数作为此特定实例上所有查询的固定值)。

我需要这个(或解决方法),因为我在数据库中有这样的视图:

CREATE VIEW ProblematicView
AS
SELECT
    v.*,
-- lots of data
FROM someView v
LEFT JOIN someTable t ON v.ForeignKey = t.ForeignKey

现在除了 ForeignKey 匹配之外,我还需要对这样的属性进行额外检查:

AND t.SomeOtherValue = @myParameter

这是不可能的,因为无法直接将参数传递给视图。使用表值函数这是可能的,但我不知道如何将它映射到 NHibernate / QueryOver。

此外,函数方法很难实现,因为使用巨大的 QueryOver 语句来过滤所有剩余的属性(因为视图用于搜索业务实体)

目前我正在将 SomeOtherValue / @myParameter 过滤器作为我的 QueryOver 的一部分应用于整个视图。

这是我的主要问题:

使用例如:

SELECT
    v.*,
-- lots of data
FROM someView v
LEFT JOIN someTable t ON v.ForeignKey = t.ForeignKey AND t.SomeOtherValue = 123
 (followed by alot of other property checks...)

将返回不同的结果(由于左连接,t.SomeOtherValue 的 NULL 条目包含在意图中)

比使用:

SELECT * FROM ProblematicView where SomeOtherValue = 123
 (followed by alot of other property checks)

由于现在左连接发生在视图内部而不检查 SomeOtherValue 并且 SomeOthervalue 检查独立于左连接应用,因此所有 NULL 值都将被排除(这是错误的业务逻辑)。

同时使用:

SELECT * FROM ProblematicView where SomeOtherValue = 123 OR SomeOtherValue = NULL
 (followed by alot of other property checks)

似乎没有帮助,因为仍然会忽略 NULL 值...

所以我能想象解决这个问题的唯一方法是找到一种方法以某种方式将我的 SomeOtherValue 属性传递给视图,以便它可以将其用作视图本身的参数(而不是在 where 子句中)或者可能以某种方式使用基于 sql 表的函数和模型参数...

编辑:

经过更多研究,我希望能简化问题:

我正在尝试转换此 SQL:

Select v.*, ... from (someView v LEFT JOIN someTable t ON v.ForeignKey = t.ForeignKey) 
WHERE SomeOtherValue = 123

(其中 SomeOtherValue 来自 someOtherTable)

到这里:

Select v.*, ... from someView v LEFT JOIN someTable t on v.ForeignKey = t.ForeignKey
AND t.SomeOtherValue = 123

使用 NHibernate / QueryOver。请注意,在第二个版本中,属性 SomeOthervalue 直接在左连接中进行检查,而在第一个版本中,它仅在左连接后才被错误地应用。

我需要找到一种方法来编写后面的 SQL 语句,以便我可以将它放在视图中,同时仍然能够将 123 作为 SomeOtherValue 的参数传递。

【问题讨论】:

    标签: c# sql nhibernate queryover


    【解决方案1】:

    您可以使用带有withClause 参数的JoinQueryOverJoinAlias 的重载向join 子句添加条件。例如:

    SomeTable stAlias = null;
    
    session.QueryOver<ProblematicView>()
        .Left.JoinAlias(
            pv => pv.SomeTable,              // Join path
            () => stAlias,                   // alias assignment
            st => st.SomeOtherValue == 123)  // "with" clause
        /* etc. */
    

    QueryOver 连接的“with”部分将向 SQL 中的left outer join 添加条件。以上应生成:

    SELECT /* select list */
    FROM   [ProblematicView] this_
           left outer join [SomeTable] sometable1_
             on this_.Id = sometable1_.ProblematicViewId
                and (sometable1.SomeOtherValue = 123 /* @p0 */)
    

    如果我理解正确,这应该帮助解决您的问题。

    添加“with”子句的几点注意事项:

    • 有趣的是,JoinQueryOverJoinAlias 的所有重载允许您指定“with”子句,要求您在执行连接时分配别名。
    • 您不能(据我所知)在连接条件中生成带有or 的SQL。 “with”子句总是anded 与映射的连接条件(即,FK → PK)

    【讨论】:

    • 感谢您的回答!您的解决方案看起来非常接近我的需要。但是我不确定如何在我的主视图模型上映射 SomeTable 属性(用于连接路径)。 ProblematicView 与 SomeTable 没有任何关系(除了外连接),无论是在 sql 视图中还是在 NHibernate 模型中。
    • @Philipp:对不起,我错过了——是的,这确实需要两者之间存在关系。不幸的是 QueryOver/Criteria/HQL 只适用于映射关系。将您的视图和视图之间的关系映射到SomeTable 有多难?
    • 没问题,您的回答仍然很有帮助,可能会为其他人解决类似的问题。您能否解释一下(在您的版本中)pv.SomeTable 将如何映射到(Fluent)NH 中。对我来说,您似乎会通过外键关系在 NH 映射中加入表一次,然后通过 QueryOver 中的左连接再次加入表,这让我有点困惑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多