NHibernate 双重获取不存在的多对一关系
我有一个具有多个多对一关系的实体,我发现我可以在一个查询中急切地获取它们,如下所示:
public Accommodation GetEager(int id)
{
IList<Accommodation> query = NHibernateSession.CurrentFor(NHibernateSession.DefaultFactoryKey)
.CreateQuery(@"
select a from Accommodation as a
left join fetch a.AccommodationType
left join fetch a.AccommodationUnitType
left join fetch a.CollectionType
where a.Id = :id
")
.SetProperties(new {id})
.SetCacheable(true)
.List<Accommodation>();
return query.SingleOrDefault();
}
但是,这些关系并不总是存在,并且我已经像这样定义了映射:
mapping.References(x => x.AccommodationUnitType).NotFound.Ignore();
我发现当关系不存在时,NHibernate 会生成第二个 SQL 查询来查找它,大概是因为它发现该属性为 null。
我的第一个问题是,如何防止第二个 sql 查询?
我的第二个问题是,是否有一种更简单的方法可以将数据提取到一个查询中?人们希望在一个查询中获取所有内容,而不是为每个多对一关系进行单独的查询(这似乎是默认行为),这似乎是非常基本的行为。
I have an entity with several Many to One relationships and I've found I can eagerly fetch them in one query like such:
public Accommodation GetEager(int id)
{
IList<Accommodation> query = NHibernateSession.CurrentFor(NHibernateSession.DefaultFactoryKey)
.CreateQuery(@"
select a from Accommodation as a
left join fetch a.AccommodationType
left join fetch a.AccommodationUnitType
left join fetch a.CollectionType
where a.Id = :id
")
.SetProperties(new {id})
.SetCacheable(true)
.List<Accommodation>();
return query.SingleOrDefault();
}
However, the relationships don't always exist, and I've defined the mappings like so:
mapping.References(x => x.AccommodationUnitType).NotFound.Ignore();
I've found that when a relationship doesn't exist, NHibernate generated a second SQL query looking for it, presumably because it's found that the property is null.
My first question is, how can I prevent this second sql query?
My second question is, is there an easier way to do this fetching into one query? It seems very basic behaviour that one would want to fetch everything in one query rather than a seperate query for each many-to-one relationship (which seems to be the default behaviour).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您确定您正确使用了
NotFound().Ignore()
吗?该设置决定了如果外键无效,NHibernate 将执行什么操作。在这种情况下,NotFound().Ignore()
会阻止抛出 EntityNotFoundException。通过设置,如果未找到相关对象,则该值为 null。如果您具有此关系的引用完整性,则不需要NotFound().Ignore()
。您看到的行为显然是预期的、众所周知的且不太可能改变。
至于你的第二个问题,我建议始终从延迟加载的默认行为开始,并且仅根据实际性能问题的需要使用急切加载进行优化。延迟加载通常比急切获取更有效,因为 a) 对象可能已经在缓存中(不需要数据库访问),并且 b) 通过主键选择非常快。具有三个联接的查询的性能很可能比按主键进行的四个选择要差。
Are you sure you're using
NotFound().Ignore()
correctly? This setting determines what NHibernate will do if there is an invalid foreign key. In that caseNotFound().Ignore()
prevents throwing an EntityNotFoundException. With the setting, if the related object is not found then the value will be null. If you have referential integrity for this relationship then you do not needNotFound().Ignore()
.The behavior you're seeing is apparently expected and well known and unlikely to change.
As for your second question, I would advise always starting with the default behavior of lazy loading and only optimizing with eager loads as needed for real world performance problems. Lazy loading is frequently more efficient than eager fetching because a) the object may already be in cache (no db trip required) and b) selecting by primary key is very fast. It's very possible that your query with three joins performs worse than four selects by primary key.