Выбор объекта с несколькими дочерними объектами - PullRequest
0 голосов
/ 14 мая 2011

Используя Active Record / NHibernate, я пытаюсь выбрать объект (сайт), который имеет несколько дочерних коллекций.

Существует только один сайт с заданным идентификатором siteId, но FindAll возвращает сайт 28 раз; он дублируется из-за дочерних коллекций, которые он загружает. Как заставить его загружать только 1 сайт и массивы дочерних коллекций? Я не против, если он выберет 5 вариантов: один для захвата сайта, а затем 1 для каждой дочерней коллекции.

Вот код:

var criteria = DetachedCriteria.For<Site>()
                    .CreateAlias("TimeZone", "tz", NHibernate.SqlCommand.JoinType.InnerJoin)
                    .CreateAlias("Logos", "l", NHibernate.SqlCommand.JoinType.LeftOuterJoin)
                    .CreateAlias("SiteColors", "sc", NHibernate.SqlCommand.JoinType.LeftOuterJoin)
                    .CreateAlias("ManagerUsers", "mu", NHibernate.SqlCommand.JoinType.LeftOuterJoin)
                    .Add(Restrictions.Eq("Id", siteId));
                var sites = FindAll(criteria);

Я должен упомянуть, что я также пробовал подход hql, используя fetch, однако fetch не получает! Он возвращает только один сайт (хорошо), но ни одна из дочерних коллекций не загружается (плохо).

public static Site Get(int id)
        {
            var query = new SimpleQuery<Site>(@"
                from Site s
                where s.Id = ?
                inner join fetch s.TimeZone tc
                left join fetch s.Logos l
                left join fetch s.SiteColors sc
                left join fetch s.ManagerUsers mu
            ", id);
            var results = query.Execute().ToList();
            return results.FirstOrDefault();
        }

Вот код, который, кажется, работает, используя подход «Будущее»:

public static Site Get(int id)
        { 
            var session = ActiveRecordMediator.GetSessionFactoryHolder().CreateSession(typeof(Site));
            var query = session.CreateQuery("from Site s left join fetch s.Logos where s.Id = :id").SetParameter("id", id).Future<Site>();
            session.CreateQuery("from Site s left join fetch s.SiteColors where s.Id = :id2").SetParameter("id2", id).Future<Site>();
            session.CreateQuery("from Site s left join fetch s.ManagerUsers where s.Id = :id3").SetParameter("id3", id).Future<Site>();
            return query.FirstOrDefault();
        }

Все мои классы модели данных наследуются от класса SimpleModel, в который я добавил методы Equals и GetHashCode:

public abstract class SimpleModel
    {
        protected SimpleModel()
        {
            DateCreated = DateTimeAccess.Now;
        }

        [PrimaryKey]
        [DocumentId]
        public virtual int Id { get; set; }

        [Property]
        public virtual DateTime DateCreated { get; set; }

        public override bool Equals(object obj)
        {
            if (obj is SimpleModel)
            {
                return Id.Equals(((SimpleModel)obj).Id);
            }
            else
            {
                return false;
            }
        }

        public override int GetHashCode()
        {
            return Id.GetHashCode();
        }
    }

1 Ответ

1 голос
/ 14 мая 2011

Звоните SetResultTransformer(DistinctRootEntity) по вашим критериям. Это свернет эти дубликаты Site в один экземпляр.

Для получения дополнительной информации см. Эту тему: http://groups.google.com/group/nhusers/browse_thread/thread/9919812230702ccc

...