NHibernate 能否在不使用批处理或 Criteria API 的情况下解决订单->客户关系的 N+1 问题?

发布于 2024-10-25 01:17:57 字数 590 浏览 5 评论 0原文

我一直在阅读和环顾四周,以白纸黑字找到这个答案。

我们来聊聊熟悉的吧 客户订单问题。让我们 假设我加载 100 个订单,每个订单 与一个且仅一个相关联 客户。

使用 Fluent NHibernate,我将使用 References() 将我的 Order 链接到 Customer,并且我将定义我的 Not.LazyLoad()Fetch.Join() 也是如此。

现在我假设,NHibernate 可以简单地连接这两个表,并且很容易水合实体。然而,在我的测试中,我总是看到 N+1 查询(实际上可能只是唯一的 ID)。我可以分享我的代码和表格,但它可能会让你感到厌烦,所以

  • 是否有可能克服订单->客户的N+1(一->一或更确切地说许多->一)?或者我必须使用批处理或 Criteria API?
  • 如果可能的话,您能给我指一个 Fluent NHibernate 示例吗?

I have been reading and looking around to find this answer in black and white.

Let's talk about the familiar
Customer and Order problem. Let's
say I load 100 orders, and each order
is linked to one and only one
customer.

Using Fluent NHibernate, I will use References() to link my Order to Customer and I will define my Not.LazyLoad() and Fetch.Join() as well.

Now I am thinking hypothetically, NHibernate can simply join these two tables and would be pretty easy to hydrate entities. However, in my tests I always see rather N+1 queries (in fact perhaps only the unique IDs). I can share my code and tables but it might bore you, so

  • Is it possible to overcome N+1 for Order->Customer (one->one or rather Many->One)? Or I have to use batching or Criteria API?
  • If possible can you please point me to an Fluent NHibernate example?

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

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

发布评论

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

评论(4

时常饿 2024-11-01 01:17:57

经常有人抱怨 fetch="join" 不不起作用。这是因为HQL没有考虑到。您可以在 HQL 中声明它。

我使用 fetch="join" 希望能够提高性能,但在很多情况下停止使用它。问题在于,连接到许多表可能会使 SQL Server 遇到最大列数限制。在某些情况下,您根本不需要这些数据,因此在映射文件中全局指定它并不是很有用。

因此,我建议

  • 在 HQL 中使用显式连接获取,因为您可以知道数据是否实际使用。
  • 或者对于任何其他情况,批处理是一个很好的解决方案,因为它们是透明的(您的代码不需要知道),利用延迟加载并同时减少 N+1 问题。

Frequently there is the complain that fetch="join" doesn't work. This is because it is not considered by HQL. You can declare it within HQL.

I used fetch="join" hoping to make performance better but stopped using it in many cases. The problem was that joining to many tables could make SQL server run into a maximal number of columns limit. In some cases you don't need the data at all and therefore it is not very useful to specify it globally in the mapping file.

So I would recommend to

  • either use explicit join fetching in HQL, because there you know if the data is actually used.
  • or for any other case, batches are a great solution, because they are transparent (your code doesn't need to know about), make use of lazy loading and reducing the N+1 problem at the same time.
眼眸里的快感 2024-11-01 01:17:57

我不会像您正在执行的实际查询那样查看映射。默认情况下,我将所有映射保留为 LazyLoad,并根据需要进行覆盖。

我使用 Criteria API 进行查询,并使用 CreateAlias 根据需要连接其他表。强烈建议 NProf 查找并消除此类情况。

I wouldn't look at the mapping as much as the actual querying you are doing. I leave ALL of my mappings as LazyLoad by default and override as needed.

I use the Criteria API to query, and I use CreateAlias to join other tables as needed. NHProf is highly recommended to find and eliminate situations like this.

自我难过 2024-11-01 01:17:57


有两种方法可以解决您的问题

a) 使用 Criteria 查询
它看起来像这样

Session.CreateQuery(typeof(Order))
.Add(<Restrictions if any>)
.SetFetchMode("Customer",FetchMode.Eager)
.List<Order>();

b) 使用 HQL

Session.CreateQuery("select o from Order inner join fetch o.Customer where <conditionifany>").List<Order>();

希望这会有所帮助..

Hi
There are two ways you can address your problem

a) Using Criteria query
It will look something like this

Session.CreateQuery(typeof(Order))
.Add(<Restrictions if any>)
.SetFetchMode("Customer",FetchMode.Eager)
.List<Order>();

b) Using HQL

Session.CreateQuery("select o from Order inner join fetch o.Customer where <conditionifany>").List<Order>();

Hope this helps..

烟雨凡馨 2024-11-01 01:17:57

您使用什么查询 API?

如果是 HQL,您可以使用 join fetch 来快速检索关联。

对于 LINQ 和 QueryOver,请使用 .Fetch()

What query API are you using?

If it's HQL, you can use join fetch to retrieve an association eagerly.

For LINQ and QueryOver, use .Fetch()

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