简体   繁体   English

NHibernate是否可以解决N + 1,而无需使用Order-> Customer关系的批处理或Criteria API?

[英]Can NHibernate solve N+1 without using batching or Criteria API for an Order->Customer relationship?

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. 让我们谈谈熟悉的“ CustomerOrder问题。 Let's say I load 100 orders, and each order is linked to one and only one customer. 假设我加载了100个订单,并且每个订单都链接到一个并且只有一个客户。

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. 使用Fluent NHibernate,我将使用References()Order链接到Customer ,还将定义Not.LazyLoad()Fetch.Join()

Now I am thinking hypothetically, NHibernate can simply join these two tables and would be pretty easy to hydrate entities. 现在,我正在假设性地考虑,NHibernate可以简单地将这两个表连接在一起,并且很容易对实体进行水合。 However, in my tests I always see rather N+1 queries (in fact perhaps only the unique IDs). 但是,在我的测试中,我总是看到N + 1个查询(实际上也许只有唯一的ID)。 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)? 是否有可能克服Order-> Customer(一个->一个或多个->一个)的N + 1? Or I have to use batching or Criteria API? 还是我必须使用批处理或Criteria API?
  • If possible can you please point me to an Fluent NHibernate example? 如果可以的话,请您为我介绍一个Fluent NHibernate示例?

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. 默认情况下,我将所有映射保留为LazyLoad并根据需要覆盖。

I use the Criteria API to query, and I use CreateAlias to join other tables as needed. 我使用Criteria API进行查询,并根据需要使用CreateAlias联接其他表。 NHProf is highly recommended to find and eliminate situations like this. 强烈建议使用NHProf来查找和消除这种情况。

Frequently there is the complain that fetch="join" doesn't work . 经常有人抱怨fetch =“ join”不起作用 This is because it is not considered by HQL. 这是因为HQL不考虑它。 You can declare it within HQL. 您可以在HQL中声明它。

I used fetch="join" hoping to make performance better but stopped using it in many cases. 我使用fetch =“ join”希望提高性能,但在许多情况下停止使用它。 The problem was that joining to many tables could make SQL server run into a maximal number of columns limit. 问题在于,连接到许多表可能会使SQL Server遇到最大列数限制。 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. 都可以在HQL中使用显式联接获取,因为在那里您知道数据是否实际使用。
  • 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. 或在任何其他情况下,批处理都是一个很好的解决方案,因为它们是透明的(您的代码不需要知道),可以利用延迟加载并同时减少N + 1问题。

Hi 你好
There are two ways you can address your problem 有两种方法可以解决您的问题

a) Using Criteria query It will look something like this a)使用条件查询它将看起来像这样

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

b) Using HQL b)使用HQL

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

Hope this helps.. 希望这可以帮助..

What query API are you using? 您正在使用什么查询API?

If it's HQL, you can use join fetch to retrieve an association eagerly. 如果是HQL,则可以使用join fetch来检索关联。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM