在NHibernate中急切地加载多级子实体会导致重复问题

发布于 2024-11-05 18:41:01 字数 1296 浏览 0 评论 0原文

我有一个模型类,其中包含一些图像和一些功能:

public class Model
{
    public int ModelId { get; set; }
    public string ModelName { get; set; }
    public virtual IList<Feature> ModelFeatures { get; set; }
    public virtual IList<ModelImage> ModelImages { get; set; }
}

public class ModelImage
{
    public virtual int ModelImageId { get; set; }
    public virtual Model Model { get; set; }
    public virtual Resource Image { get; set; }
    public virtual int DisplayOrder { get; set; }
}

public class Feature
{
    public virtual int FeatureId { get; set; }
    public virtual string Title { get; set; }
    public virtual string Text { get; set; }
}

现在我想急切地加载模型的 ModelImages 和功能,我正在使用:

item = session.CreateCriteria<Model>()
       .Add(NHibernate.Criterion.Expression.Where<Model>(o => o.ModelId == id))
       .SetFetchMode("ModelImages", NHibernate.FetchMode.Eager)
       .SetFetchMode("ModelImages.Image", NHibernate.FetchMode.Eager)
       .SetFetchMode("ModelFeatures", NHibernate.FetchMode.Eager)
       .SetResultTransformer(NHibernate.Transform.Transformers.DistinctRootEntity)
       .UniqueResult<Model>();

但结果包含重复的 ModelImage 和 ModelFeatures, 我如何将结果转换器(例如 DistinctRoot)应用于这些子集合?

谢谢

i have a Model class which contains some images and some features :

public class Model
{
    public int ModelId { get; set; }
    public string ModelName { get; set; }
    public virtual IList<Feature> ModelFeatures { get; set; }
    public virtual IList<ModelImage> ModelImages { get; set; }
}

public class ModelImage
{
    public virtual int ModelImageId { get; set; }
    public virtual Model Model { get; set; }
    public virtual Resource Image { get; set; }
    public virtual int DisplayOrder { get; set; }
}

public class Feature
{
    public virtual int FeatureId { get; set; }
    public virtual string Title { get; set; }
    public virtual string Text { get; set; }
}

now i want to load ModelImages and Features of a Model eagerly, i'm using :

item = session.CreateCriteria<Model>()
       .Add(NHibernate.Criterion.Expression.Where<Model>(o => o.ModelId == id))
       .SetFetchMode("ModelImages", NHibernate.FetchMode.Eager)
       .SetFetchMode("ModelImages.Image", NHibernate.FetchMode.Eager)
       .SetFetchMode("ModelFeatures", NHibernate.FetchMode.Eager)
       .SetResultTransformer(NHibernate.Transform.Transformers.DistinctRootEntity)
       .UniqueResult<Model>();

but the result contain duplicate ModelImage and ModelFeatures,
how could i apply a result transformer such as DistinctRoot to these child collections ?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(2

放肆 2024-11-12 18:41:01

我会将查询分为两部分:

item = session.CreateCriteria<Model>()
   .Add(NHibernate.Criterion.Expression.Where<Model>(o => o.ModelId == id))
   .SetFetchMode("ModelFeatures", NHibernate.FetchMode.Eager)
   .UniqueResult<Model>();

session.CreateCriteria<Model>()
   .Add(NHibernate.Criterion.Expression.Where<Model>(o => o.ModelId == id))
   .SetFetchMode("ModelImages", NHibernate.FetchMode.Eager)
   .SetFetchMode("ModelImages.Image", NHibernate.FetchMode.Eager)
   .UniqueResult<Model>();

第二个查询只是继续填充第一个查询返回的“item”对象的集合,因此不需要使用第二个查询的返回值。

如果您希望在一次往返中执行这两个查询,您可以使用 Future() 而不是 UniqueResult(),然后使用 item.Value 实际执行查询。

I would split the query into two parts:

item = session.CreateCriteria<Model>()
   .Add(NHibernate.Criterion.Expression.Where<Model>(o => o.ModelId == id))
   .SetFetchMode("ModelFeatures", NHibernate.FetchMode.Eager)
   .UniqueResult<Model>();

session.CreateCriteria<Model>()
   .Add(NHibernate.Criterion.Expression.Where<Model>(o => o.ModelId == id))
   .SetFetchMode("ModelImages", NHibernate.FetchMode.Eager)
   .SetFetchMode("ModelImages.Image", NHibernate.FetchMode.Eager)
   .UniqueResult<Model>();

The second query just continues to populate the collections of the "item" object returned from the first query, so there is no need to use the return value from the second query.

If you want those two queries to be executed in a single round trip you can use Future() instead of UniqueResult() and then use item.Value to actually execute the queries.

夜声 2024-11-12 18:41:01

谢谢 Erik,

NHibernate 中没有标准的方法来做到这一点,这真的很烦人。或者也许我有设计问题?无论如何,我还记得为了避免重复的实体,我们可以在映射中使用 Set 而不是 Bag。

所以我改变了

<bag name="ModelImages" table="ModelImages" cascade="all-delete-orphan" inverse="true">
  <key column="ModelId"/>
  <one-to-many class="ModelImage"/>
</bag>

<set name="ModelImages" table="ModelImages" cascade="all-delete-orphan" inverse="true">
  <key column="ModelId"/>
  <one-to-many class="ModelImage"/>
</set>

Thank you Erik,

it's really annoying that there is not a standard way to do so in NHibernate. or maybe i have a design problem ? anyway i also remembered that to avoid duplicate entities we could use a Set instead of using a Bag in our mapping.

so i changed :

<bag name="ModelImages" table="ModelImages" cascade="all-delete-orphan" inverse="true">
  <key column="ModelId"/>
  <one-to-many class="ModelImage"/>
</bag>

to

<set name="ModelImages" table="ModelImages" cascade="all-delete-orphan" inverse="true">
  <key column="ModelId"/>
  <one-to-many class="ModelImage"/>
</set>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文