Используя 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();
}
}