当我有一个一对多的子集合一个实体对象,我需要查询特定的子对象,是有一个功能或一些聪明的模式我还没有想出尚未避免NHibernate的取整子集?
例:
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
}
}
}
我知道这是不是最好的例子,因为在这种情况下,人们可能只是直接查询儿童的实体,但我也遇到过,我已经有了一个父对象,并通过它来遍历特定子树需要的情况。
简短的回答:没有。 较长的答案:你可以把它做到这一点,与手的一些花招。
上述Rippo的回答表明,你会怎么做了“适当的” NHibernate的方式(无论是使用LINQ或QueryOver或HQL其实并不重要 - 关键是你要踩父外 - >亲子关系做一个查询)。 您可以更进一步借此和掩盖这个幌子。 但要做到这一点,你必须完全移除映射关系,并在任何时候的查询替换它。 你会拿出父 - >儿童的映射,但留下孩子 - >父映射完好; 然后重新写上父母的财产,以这个样子:
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
你回来可查询的集合,所以你可以接着写
IEnumerable<Child> childrenNamedBob = parent.Children.Where(c => c.Name == "Bob");
你能做到这一点,并保留映射的唯一方法是修改NHibernate的集合对象(或注入自己)。 迭戈Mijelshon(谁是围绕这些部件)写的正是这样一个尖峰,增加IQueryable的支持NHibernate的集合,所以你可以做
IEnumerable<Child> childrenNamedBob = parent.Children.AsQueryable().Where(c => c.Name == "Bob");
但是,从我所看到的,这个再没有什么长进,而且也没有明显的计划,这个功能添加到NH。 我已经运行迭戈的代码和它的工作,但显然它不是生产质量并没有经过测试,我不认为这是以往任何时候都正式“发布”甚至作为一个私人的补丁。
这里的链接到讨论的NH问题跟踪: https://nhibernate.jira.com/browse/NH-2319
我相信NH应该支持这个开箱即用,因为它是大多数.NET开发者想与几乎任何枚举交互的自然方式,现在我们有LINQ的,并且无副作用不能够做到这一点加载无限收集到RAM很烂。 但传统的NH模型会议 - >查询,这就是99%的人使用。
我问上NHusers同样的问题在几个星期前,所以我怀疑,答案是没有得到答案you will always get all the parents children and then perform a in-memory filter
。 在许多情况下,这可能是在看到它的正确方法。
在你的情况我会重写查询是: -
var childrenNamedBob = session.Query<Children>()
.Where(w => w.Parent.Id == parentId && w.Name == "Bob");
然后,只需获得母公司(如果childrenNamedBob有结果),你可以拨打电话: -
var parent = childrenNamedBob.First().Parent;
或者你正确地指出: -
var parent = session.Get<Parent>(parentId);
现在你可以做到这一点与NHibernate 5的情况下直接特定的代码!
见https://github.com/nhibernate/nhibernate-core/blob/master/releasenotes.txt
Build 5.0.0
=============================
** Highlights
...
* Entities collections can be queried with .AsQueryable() Linq extension without being fully loaded.
...
文章来源: Can NHibernate query for specific children without lazy loading the entire collection?