【问题标题】:NHibernate: Select one to Many Left Join - Take X latest from ParentNHibernate:选择一对多左加入 - 从父级获取 X 最新
【发布时间】:2015-02-25 20:14:56
【问题描述】:

我有以下物品:

Parent
   public virtual Guid Id { get; set; }
   public virtual DateTime TimeStamp { get; set; }
   public virtual IList<Child> Childs { get; set; }

Child
   public virtual Guid Id { get; set; }
   public virtual string Name { get; set; }

我使用 Fluent 将一对多映射如下:

.Override<Parent>(obj =>obj.HasMany(x => x.Childs)
                                .Cascade.All()
                                .Not.Inverse()
                                .Not.KeyNullable()
                                .Not.KeyUpdate())

我需要在日期之间按时间戳顺序联系所有有孩子的父母。

我正在尝试按以下方式进行操作(maxCapacity 为 int):

QueryOver<Parent>().Where(x => x.TimeStamp > from)
            .And(x => x.TimeStamp < to).OrderBy(x => x.TimeStamp).Desc
            .Left.JoinQueryOver<Child>(x => x.Childs)
            .TransformUsing(new DistinctRootEntityResultTransformer())
            .Take(maxCapacity).List();

结果不是我所期望的,因为 Take(maxCapacity) 不在父结果上,而是在包括父和子的总查询结果上。

如何获取最新的 X 已经转换的 Parent 行?

谢谢。

【问题讨论】:

    标签: nhibernate fluent-nhibernate left-join queryover


    【解决方案1】:

    我会去这里的方式是:

    • 加载根实体(父)列表并
    • 让 NHibernate 懒惰地加载他们的孩子 - 在单独的 SQL 查询中。

    为了避免 1 + N 的问题,我们可以使用智能地图功能:

    19.1.5. Using batch fetching

    NHibernate 可以有效地利用批量获取,也就是说,如果访问一个代理(或集合),NHibernate 可以加载多个未初始化的代理。批量获取是对惰性选择获取策略的优化。有两种方法可以调整批量获取:在类和集合级别。

    类/实体的批量获取更容易理解。假设您在运行时有以下情况:您在一个 ISession 中加载了 25 个 Cat 实例,每个 Cat 都有一个对其所有者的引用,即一个 Person。 Person 类使用代理lazy="true" 进行映射。如果您现在遍历所有猫并在每个猫上调用 cat.Owner,NHibernate 将默认执行 25 条 SELECT 语句,以检索代理所有者...

    所以,查询应该是这样的:

    session.QueryOver<Parent>()
        .Where(x => x.TimeStamp > from)
        .And(x => x.TimeStamp < to).OrderBy(x => x.TimeStamp).Desc
        //.Left.JoinQueryOver<Child>(x => x.Childs)
        // .TransformUsing(new DistinctRootEntityResultTransformer())
        .Skip(start) // paging
        .Take(maxCapacity)
        .List<Parent>();
    

    父映射应该是这样的:

    <class name="Parent">
        ...
        <bag name="Childs" batch-size="3">
            ...
        </bag>
    </class>
    

    请检查这些:

    【讨论】:

    • 感谢您的回答。我的问题: 1. NHibernate 是否支持 SQL CE 数据库的批量获取? 2. 属性“batch-size="3" 是否意味着每次加载3个孩子?
    • 我使用了 3,因为该值在文档中。所以抱歉——正确的设置应该是 25 或 50。(出于某种原因,NHibernate 正在使用该设置的一半,即 12 或 25——不要问我为什么;)以及 SQL CE 的答案- 是的,任何数据库引擎都可以批量获取......请尝试一下。值为 25。这是我在 1)每个班级和 2)每个包上的设置:batch-size="25"
    • 根据您的回答,我不应该使用加入。那么如何加载孩子呢?通过 LoadList:NHibernateUtil.Initialize(Parent.Childs) ?
    • 在继续预加载:什么是预加载的最佳方式:Fetch、NHibernateUtil.Initialize、Future...?
    • 老实说,我不在乎如何加载孩子。我只是尽可能长时间地保持会话打开。因为我的世界是网络,这意味着 - 通过所有网络请求保持开放。如果需要集合,NHibernate 将加载它(它们)。如果不是 - all 将是一个代理,它永远不会被加载 === 非常有效。所以我真的不在乎。这就是好处。如果您真的需要它,那么最有效的方法是:询问第一项(父)子集合的计数。这将导致完全加载(感谢批量获取)。希望对您有所帮助...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-10
    • 1970-01-01
    相关资源
    最近更新 更多