NHibernate可以在不延迟加载整个集合的情况下查询特定的孩子吗? [英] Can NHibernate query for specific children without lazy loading the entire collection?

查看:65
本文介绍了NHibernate可以在不延迟加载整个集合的情况下查询特定的孩子吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我有一个带有一对多子集合的实体对象,并且我需要查询一个特定的子对象时,有没有我想不出的功能或一些聪明的模式来避免NHibernate获取整个子集合?

When I have an entity object with a one-to-many child collection, and I need to query for a specific child object, is there a feature or some clever pattern I haven't come up with yet to avoid that NHibernate fetches the entire child collection?

示例:

class Parent 
{
    public virtual int Id { get; proteced set; } // generated PK
    public virtual IEnumerable<Child> Children { get; proteced set; }
}

class Child
{
    public virtual int Id { get; protected set; } // generated PK
    public virtual string Name { get; protected set; }
    public virtual Parent Parent { get; protected set; }
}

// mapped with Fluent

class Service
{

    private readonly ISessionFactory sessionFactory;

    public Service(ISessionFactory sessionFactory)
    {
        this.sessionFactory = sessionFactory;
    }

    void DoSomethingWithChildrenNamedBob(int parentId)
    {
        using(var session = sessionFactory.OpenSession())
        {
            var parent = session.Get<Parent>(parentId);
            // Will cause lazy fetch of all children!
            var childrenNamedBob = parent.Children.Where(c => c.Name == "Bob"); 
            // do something with the children
        }
    }
}

我知道这不是最好的例子,因为在这种情况下,可能只是直接查询Child实体,但是我遇到的情况是我已经有一个Parent对象,需要遍历它的特定子树.

I know it's not the best example because in this case one would probably just query the Child entities directly, but I have encountered situations where I already had a Parent object and needed to traverse specific sub-trees through it.

推荐答案

简短答案:否.更长的答案:您可以花些力气就能做到这一点.

Short answer: no. Longer answer: you can make it do this, with some sleight of hand.

Rippo上面的答案显示了如何以正确的NHibernate方式进行操作(无论是与Linq还是QueryOver或HQL无关紧要-关键是您必须走出父级->子级关系才能做到)询问).您可以更进一步,将其掩藏在立面的后面.但是要这样做,您必须完全删除映射关系,并始终用查询替换它.您将取出父"->子"映射,但保留子"->父"映射不变;然后在Parent上重新编写该属性,如下所示:

Rippo's answer above shows how you would do it the 'proper' NHibernate way (whether it's with Linq or QueryOver or HQL doesn't really matter - the point is you have to step outside the parent -> child relationship to do a query). You can take this a step further and disguise this behind a façade. But to do so, you have to remove the mapped relationship entirely and replace it with a query at all times. You'd take out the Parent -> Children mapping, but leave the Child -> Parent mapping intact; then re-write the property on Parent to look like this:

public virtual IQueryable<Child> Children
{
    get
    {
        // somehow get a reference to the ISession (I use ambient context), then
        return session.Query<Child>().Where(c => c.Parent == this);
    }
}

现在,当您使用Parent.Children时,您将获得一个可查询的集合,因此您可以编写

Now, when you use Parent.Children you get back a queryable collection, so you could then write

IEnumerable<Child> childrenNamedBob = parent.Children.Where(c => c.Name == "Bob");

您可以执行此操作并保留映射的唯一方法是修改NHibernate的集合对象(或注入您自己的对象). Diego Mijelshon(围绕这些部分)写了一个尖峰,为NHibernate集合添加了IQueryable支持,因此您可以做到

The only way you could do this and preserve the mapping is to amend NHibernate's collection objects (or inject your own). Diego Mijelshon (who is around these parts) wrote a spike of exactly that, adding IQueryable support to NHibernate collections so you could do

IEnumerable<Child> childrenNamedBob = parent.Children.AsQueryable().Where(c => c.Name == "Bob");

但是据我所见,这再也没有进行过了,也没有明显的计划将此功能添加到NH中.我已经运行了Diego的代码,并且确实可以运行,但是显然它不是生产质量,也没有经过测试,而且我认为它甚至没有作为私有补丁正式发布过.

But from what I can see, this never went any further and there's no apparent plan to add this capability to NH. I have run Diego's code and it does work, but obviously it's not production quality and hasn't been tested, and I don't think it's ever been officially 'released' even as a private patch.

以下是NH问题跟踪器上的讨论链接: https://nhibernate.jira. com/browse/NH-2319

Here's the link to the discussion on the NH issue tracker: https://nhibernate.jira.com/browse/NH-2319

我相信NH应该开箱即用地支持这一点,因为对于大多数.NET开发人员来说,这是自然的方式,它想与几乎所有可枚举的东西进行交互,因为我们有了Linq,并且没有侧边就无法做到-将无限集合加载到RAM的效果很糟糕.但是传统的NH模式是会话->查询,这就是99%的人使用的方式.

I believe NH should support this out of the box, as it's a natural way for most .NET devs to want to interact with pretty much anything enumerable, now that we have Linq, and not being able to do it without the side-effect of loading an unbounded collection into RAM sucks. But the traditional NH model is session -> query and that's what 99% of people use.

这篇关于NHibernate可以在不延迟加载整个集合的情况下查询特定的孩子吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆