NHibernate 双重获取不存在的多对一关系

发布于 2024-09-27 09:50:20 字数 927 浏览 1 评论 0原文

我有一个具有多个多对一关系的实体,我发现我可以在一个查询中急切地获取它们,如下所示:

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 技术交流群。

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

发布评论

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

评论(1

心在旅行 2024-10-04 09:50:20

您确定您正确使用了 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 case NotFound().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 need NotFound().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.

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