NHibernate 3.1.0.4000 QueryOver SQL Оптимизация - PullRequest
0 голосов
/ 15 августа 2011

У меня есть Entity 'Content'. Каждый Контент имеет свойство «Место размещения». Место размещения имеет сущность AdType ширины отношения "многие ко многим" (у Местоположения есть сопоставленное свойство IList <\ AdType>).

Мне нужно загрузить все Места размещения, которые используются хотя бы в одном Контенте и соответствующей ширине, указанной AdType.

Моя функция DAL выглядит следующим образом:

    public IList<Placement> Load(AdType adType)
    {
        return NHibernateSession.QueryOver<Content>()
            .JoinQueryOver(content => content.Placement)
            .JoinQueryOver<AdType>(placement => placement.AdTypes)
            .Where(_adType => _adType.Id == adType.Id)
            .Select(x => x.Placement).List<Placement>();
    }

Это прекрасно работает, но когда я смотрю на журнал SQL, я вижу:

SELECT this_.PlacementId as y0_ FROM AdManager.dbo.[Content] this_ inner join AdManager.dbo.[Placement] placement1_ on this_.PlacementId=placement1_.PlacementId inner join AdManager.dbo.AdTypeToPlacement adtypes5_ on placement1_.PlacementId=adtypes5_.PlacementId inner join AdManager.dbo.[AdType] adtype2_ on adtypes5_.AdTypeId=adtype2_.AdTypeId WHERE adtype2_.AdTypeId = @p0

SELECT placement0_.PlacementId as Placemen1_26_0_, placement0_.Name as Name26_0_ FROM AdManager.dbo.[Placement] placement0_ WHERE placement0_.PlacementId=@p0

SELECT placement0_.PlacementId as Placemen1_26_0_, placement0_.Name as Name26_0_ FROM AdManager.dbo.[Placement] placement0_ WHERE placement0_.PlacementId=@p0

Это означает, что NHibernate берет все идентификаторы мест размещения в первом запросе, а затем запрашивает все поля из таблицы мест размещения по идентификатору.

Мой вопрос: знает ли enyone, как изменить метод QueryOver для принудительной загрузки данных NHibernate в одном запросе?

1 Ответ

0 голосов
/ 17 августа 2011

кажется, что NHibernate действительно думает, что может быть что-то в этом месте, которое может отфильтровывать данные, которые необходимы для инициализации размещения. Вы можете перейти с подзапросом:

public IList<Placement> Load(AdType adType)
{
    var subquery = QueryOver.For<Content>()
        .JoinQueryOver(content => content.Placement)
        .JoinQueryOver<AdType>(placement => placement.AdTypes)
        .Where(_adType => _adType.Id == adType.Id)
        .Select(x => x.Id);

    return NHibernateSession.QueryOver<Content>()
        .WithSubquery.Where(content => content.Id).IsIn(subquery))
        //.Fetch(x => x.Placement).Eager   try with and without
        .Select(x => x.Placement).List<Placement>();
}

или SQL (имеет тот недостаток, что он просто заполняет новое место размещения, но отслеживает его)

public IList<Placement> Load(AdType adType)
{
    return NHibernateSession.CreateSQLQuery("SELECT p.Name as Name, ... FROM content c join placement p...")
        .SetResultTransformer(Transformers.AliastoBean<Placement>())
        .List<Placement>();
}
...