【问题标题】:NHibernate - Duplicate Records with lazily mapped collectionNHibernate - 具有延迟映射集合的重复记录
【发布时间】:2014-01-24 04:01:57
【问题描述】:

全部,

我有一个实体,它有几个集合,每个集合都是惰性映射的。当我运行条件查询时,我在结果集中得到了我的根实体的重复结果。当我所有的收藏都被懒惰地映射时,这怎么可能!

我验证了,我的收藏,懒加载。

这是我的地图:

根实体“项目”:

[Bag(0, Lazy = CollectionLazy.True, Inverse = true, Cascade = "all-delete-orphan")]
    [Key(1, Column = "job_id")]
    [OneToMany(2, ClassType = typeof(ProjectPlan))]
    public virtual IList<ProjectPlan> PlanList
    {
        get { return _planList; }
        set { _planList = value; }
    }

条件查询是:

    ICriteria criteria = session.Session.CreateCriteria<Entities.Project>()
                    .Add(Restrictions.Eq(Entities.Project.PROP_STATUS, !Entities.Project.STATUS_DELETED_FLAG));
                    .CreateAlias(Entities.Project.PROP_PLANLIST, "p")
                    .Add(Restrictions.Eq("p.County", 'MIDDLSEX'))
.setFirstResult(start).setMaxResults(pageSize)
                    .List<Entities.Project>();

我知道,我可以用 Distinct result transformer 纠正这个问题,我只是想知道这是否是惰性集合的正常行为。

编辑:我发现了这个问题的原因——查看原始 SQL 时,连接和 where 子句是正确的,但让我感到困惑的是生成的 Select 子句——它不仅包含来自项目实体的列(根实体),还有来自项目计划实体的列,导致我上面描述的问题。我现在不在工作,但我会尝试这样做:.SetProjection(Projections.RootEntity()),所以我只在 select 子句中获取 Project 的列。

【问题讨论】:

标签: asp.net nhibernate nhibernate-criteria


【解决方案1】:

一种方法,如何解决这个(我会这么说通常的情况)是:1)不要在查询中使用获取集合,2)使用批量获取,作为映射

因此,我们将始终查询根实体。这将为我们提供一个扁平的结果集,可以正确地用于分页

为了获取每个接收行的收集数据,并避免 1 + N 问题(收集每条记录),我们将使用 19.1.5. Using batch fetching

映射是这样的

[Bag(0, Lazy = CollectionLazy.True
      , Inverse = true
      , Cascade = "all-delete-orphan"
      , BatchSize = 25)] // Or something similar to batch-size="25"
[Key(1, Column = "job_id")]
[OneToMany(2, ClassType = typeof(ProjectPlan))]
public virtual IList<ProjectPlan> PlanList
{
   ...

其他一些类似的质量检查(具有几乎相同的细节)

我们仍然可以过滤 收藏品!但是我们必须使用子查询,例如Query on HasMany reference

【讨论】:

  • 我不同意你的观点,批量大小仅控制在获取给定项目的当前集合时要预取的额外集合的数量。如果您查看我的映射,我正在使用延迟加载, - 没有批量大小,它根本不会预取集合。如果您还注意到 cirteria,我正在获取根实体 .List(),它是根实体,我不明白为什么它在选择中有其他列(除根实体列之外)补水结果时不使用的语句。
  • .CreateAlias(Entities.Project.PROP_PLANLIST, "p") 就是答案。这是“获取”,实际上这是“JOIN”,它使您的 根实体 选择乘以集合中的项目数量。我想向您解释的是:不要获取(即不要使用CreateAliasCreateCriteriaSetFetchMode)。所有这些都会使结果成倍增加。而是更改您的映射。将 batch-size 放在每个集合映射上。最后,您将在一个 SELECT 和几个加载(惰性)集合的 SQL 选择语句中获得平面根实体。现在更清楚了吗? ;)
  • .CreateAlias(Entities.Project.PROP_PLANLIST, "p"),我想,这应该只改变 from, where 子句,但我想我错了。我想,批量大小只控制预取,但现在你告诉我它也会影响 select 子句(我在 hibernate 文档中的任何地方都没有找到)?我不知道,我一定会试试这个。请记住,我的集合已经映射为惰性。我有其他解决方案,比如尝试 SetProjection(RootEntity()),或者使用带有返回 Id 的子查询,仅在返回我的根实体列表时提供主查询。感谢您的帮助。
  • 请稍等:让我澄清一下:CreateAliasCreateCriteriaSetFetchMode 是如何使用更多 JOINed 扩展当前 SELECT FROM 子句的方法表。但是 mapping attribute batch-size="25" resp BatchSize(25) in Fluent 根本不会影响当前的 SELECT 子句。此设置(批量大小的映射) 是如何优化 expost...延迟加载的方式。不要去获取 1+N 条记录,而是批量执行更少的 1+M 语句……。希望这会有所帮助;)祝 NHibernate 好运
  • 是的,这是有道理的,感谢您的澄清。
猜你喜欢
  • 2013-09-01
  • 1970-01-01
  • 2013-10-07
  • 2011-02-02
  • 2012-04-29
  • 1970-01-01
  • 2012-02-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多