在 nHibernate 查询中遇到左连接问题

发布于 2024-12-18 08:17:38 字数 689 浏览 8 评论 0原文

我正在努力在 nHibernate 查询中复制一个简单的 sql 左连接。 SO 上的其他答案让我更加困惑,什么是解决域查询中左连接的最明智的方法。

示例:

2 个数据库表:

Customer
CustId  INT PK

Orders
OrderId INT PK
CustId  INT FK
Status  INT

1 个 SQL 查询:

Select c.CustId from Customer c
left join Orders o on o.CustId = c.CustId and o.Status = 2
where o.OrderId is null

这将检索没有状态 2 订单的客户的唯一列表, 请注意,它还包括根本没有订单的客户。 这是一个为了简化这个问题而设计的示例,但是这种类型的查询非常有用,并且不容易以任何其他方式进行。

想象一下“客户”和“订单”的 nh 映射,它简单地反映了上面的示例表。

有没有一种简单的方法可以在查询中提取 nHibernate 中唯一的非 status-2 客户列表,而无需诉诸 SQL 查询或最终陷入选择 n+1 场景?

查询首选项:

1 linq-to-nhibernate
2 查询
3 HQL
4 标准。

谢谢。

I'm struggling to replicate a simple sql left join in a nHibernate query. Other answers on SO have led me to be more confused as to what is the smartest way to tackle left joins in a domain query.

Example:

2 DB Tables:

Customer
CustId  INT PK

Orders
OrderId INT PK
CustId  INT FK
Status  INT

1 SQL Query:

Select c.CustId from Customer c
left join Orders o on o.CustId = c.CustId and o.Status = 2
where o.OrderId is null

This will retrieve a unique list of Customers who don't have an order in status 2,
Note, it also includes customers who don't have an order at all.
This is a contrived example to simplify this question, but this type of query is very useful and not easy to do any other way.

Imagine nh mappings for "Customer" and "Orders" which simply reflect the example tables above.

Is there a simple way to extract my list of unique, non-status-2 customers in nHibernate, in a query, without resorting to a SQL query or ending up in a select n+1 scenario?

Query preferences:

1 linq-to-nhibernate
2 QueryOver
3 HQL
4 Criteria.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

小嗲 2024-12-25 08:17:38

请参阅 http://docs .jboss.org/hibernate/core/3.6/reference/en-US/html/queryhql.html#queryhql-joins。这是 Hibernate 参考,而不是 nHibernate 参考,但我假设它们的工作原理相同(顺便说一句,这篇文章似乎证实了这一点):

您可以使用 HQL with 关键字提供额外的连接条件。

来自猫作为猫
左加入 cat.kittens 作为 kitten
与小猫.bodyWeight > 10.0

所以,在你的情况下,它应该看起来像

select c.CustId from Customer c
left join Orders o with o.Status = 2

See http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/queryhql.html#queryhql-joins. It's the Hibernate reference, and not the nHibernate reference, but I'd assume they work the same (BTW, this post seems to confirm it):

You may supply extra join conditions using the HQL with keyword.

from Cat as cat
left join cat.kittens as kitten
with kitten.bodyWeight > 10.0

So, in your case, it should look like

select c.CustId from Customer c
left join Orders o with o.Status = 2
青朷 2024-12-25 08:17:38

NHibernate 3.0 有一个 ICriteria .CreateAlias 的重载方法,它需要 4 个参数,最后一个参数是 withClause。

这是一个示例:

 DetachedCriteria criteria = DetachedCriteria.For<Models.BO.Customer>("customer")
            .CreateAlias(ReflectionHelper.PropertyName<Models.BO.Customer>(x => ((Models.BO.Interfaces.ICustomerQueryOnly) x).Tasks),
                "activeTasks", JoinType.LeftOuterJoin, Restrictions.IsNotNull("activeTasks.LockedBy")
            )
            .CreateAlias(ReflectionHelper.PropertyName<Models.BO.Customer>(x => ((Models.BO.Interfaces.ICustomerQueryOnly) x).Tasks2),
                "availableTasks", JoinType.LeftOuterJoin,
                availableTasksRestraction
            )
            .Add(Restrictions.Eq("CustomerBase", _customerBase))
            .Add(Restrictions.Eq("IsActive", true));

最终结果如下:

     FROM Customers c
         left join Tasks t on t.customerId = c.Id and (t.DeletedDate is null and 
t.lockedById is null and [etc])
         left join Tasks activetasks [etc]
     where [...]

在这个示例中,我需要提取所有客户以及每个客户的可用任务数量和活动任务数量。

NHibernate 3.0 has an overload method for ICriteria .CreateAlias which takes 4 params, the last param is withClause.

Here is an example:

 DetachedCriteria criteria = DetachedCriteria.For<Models.BO.Customer>("customer")
            .CreateAlias(ReflectionHelper.PropertyName<Models.BO.Customer>(x => ((Models.BO.Interfaces.ICustomerQueryOnly) x).Tasks),
                "activeTasks", JoinType.LeftOuterJoin, Restrictions.IsNotNull("activeTasks.LockedBy")
            )
            .CreateAlias(ReflectionHelper.PropertyName<Models.BO.Customer>(x => ((Models.BO.Interfaces.ICustomerQueryOnly) x).Tasks2),
                "availableTasks", JoinType.LeftOuterJoin,
                availableTasksRestraction
            )
            .Add(Restrictions.Eq("CustomerBase", _customerBase))
            .Add(Restrictions.Eq("IsActive", true));

which endup with something like:

     FROM Customers c
         left join Tasks t on t.customerId = c.Id and (t.DeletedDate is null and 
t.lockedById is null and [etc])
         left join Tasks activetasks [etc]
     where [...]

In this example I need to extract all customers and number of available tasks and number of active task for each customer.

陌伤ぢ 2024-12-25 08:17:38

如果实体不相关并且您不希望映射关系,则可以使用 theta 连接。请参阅 这里

也许是这样的

Select c from Customer c, Order o 
where o.CustId = c.CustId and o.Status = 2

If the entities are unrelated and you don't wish to map a relation, you can use a theta join. See here

Maybe something like

Select c from Customer c, Order o 
where o.CustId = c.CustId and o.Status = 2
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文