загрузка многоуровневых дочерних объектов в NHibernate вызывает проблему дублирования - PullRequest
0 голосов
/ 07 мая 2011

У меня есть класс Model, который содержит несколько изображений и некоторые функции:

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, к этим дочерним коллекциям?

Спасибо

Ответы [ 2 ]

0 голосов
/ 07 мая 2011

Спасибо, Эрик,

действительно досадно, что в NHibernate нет стандартного способа сделать это.или может у меня проблема с дизайном?В любом случае, я также вспомнил, что во избежание дублирования сущностей мы могли бы использовать Набор вместо использования 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>
0 голосов
/ 07 мая 2011

Я бы разделил запрос на две части:

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 для фактического выполнения запросов.

...