NHibernate 3.1.0.4000 QueryOver SQL优化

时间:2011-08-15 14:05:21

标签: sql nhibernate queryover

我有实体'内容'。每个内容都有一个'Placement'属性。展示位置具有多对多关系宽度“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会在第一个查询中获取所有展示位置ID,然后通过ID查询展示位置表中的所有字段。

我的问题是:enyone是否知道如何修改QueryOver方法以强制NHibernate在一个查询中加载数据?

1 个答案:

答案 0 :(得分:0)

似乎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(缺点是它只填充新的Placement但是会跟踪它)

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>();
}