NHibernate:如何通过一个没有lazyload的sql查询,通过子实体上的过滤器来获取子实体?

时间:2013-08-20 11:47:16

标签: c# c#-4.0 nhibernate fluent-nhibernate hql

我正在使用NHibernate 3.3.1和FluentNhibernate 1.3进行数据层。

我有以下实体:

enter image description here

数据库图表: enter image description here

我需要一种方法来获取产品媒体的MediaCategory的产品。我希望NHibernate只向db发送一个查询并获取产品的所有子属性。

我希望NHibernate发送如下查询:

declare @mediaCategoryId int = 13
select * 
from Product p 
inner join Media m on m.ProductId=p.Id 
inner join MediaCategoryMedia mcm on mcm.MediaId=m.Id 
inner join MediaCategory mc on mc.Id=mcm.MediaCategoryId 
left join ProductSeller ps on ps.ProductId=p.Id 
left join Seller s on ps.SellerId=s.Id 
where mc.Id=@mediaCategoryId 

我尝试了以下选项来解决这一挑战;

  1. 会话.QueryOver< ProductEntity >() ...
    我尝试了Inner.JoinQueryOver< .. >().Fetch.Eager ...但我无法获取所有子实体。

  2. session.CreateCriteria< ProductEntity >().SetFetchMode("",FetchMode.Eager) ...
    在这种情况下,延迟加载工作,我不想要lazyload。如果我从映射中禁用lazyload,NH会发送大量查询..我想要的是一个单一查询来获取所有子实体。

  3. session.Query< ProductEntity >().FetchMany(p=>p.MediaList).ThenFetchMany(m=>m.SellerList) ...
    在这种情况下,我无法创建传递mediaCategoryId过滤器的别名。相反,我使用.Where(x=>x.MediaList.Any(m=>m.CategoryList.Any(...)))并且生成的查询也不是最佳的。

  4. (来自会话中的p。查询&lt; ProductEntity&gt;()
           来自p.MediaList中的m        来自c.m.MediaCategoryList中的c        其中c.Id == 23
           select p).Fetch(x =&gt; x.MediaList);

    这也不是我想要的......

  5. var hql=@"select p from ProductEntity as p join fetch p.MediaList as m join fetch m.MediaCategoryList as mc left join fetch p.SellerList as s where mc.Id=:catId ";
    这适用于hql中的“join fetch” 我需要这种情况的最佳实践,但Hql是国王。

    我们可以使用session.Query<>()session.CreateCriteria,QueryOver处理此案例吗?

1 个答案:

答案 0 :(得分:6)

直接翻译您的查询...

Media mediaAlias = null;
MediaCategory categoryAlias = null;

return session.QueryOver<Product>()
    .JoinAlias(x => x.Medias, () => mediaAlias)
    .JoinAlias(() => mediaAlias.Categories, () => categoryAlias)
    .Fetch(x => x.Sellers).Eager
    .Where(() => categoryAlias.Id == mediaCategoryId)
    .List();
默认情况下,

JoinAlias执行内连接,Fetch(...).Eager执行左外连接。 JoinAlias允许我们通过媒体挖掘类别,并且还急切地获取数据。

请注意,此查询中的卖家和媒体之间存在笛卡尔积。如果单个产品上有20个Medias和20个Sellers,则此查询将返回20 * 20 = 400行,这对于性能而言并不理想。您可以通过将媒体提取和卖方提取分成单独的查询来解决此问题,但是使用Future()将它们一起批量处理到数据库,这意味着查询将返回20 + 20 = 40行。好多了。

此外,此查询不会返回与媒体关联的所有类别。如果需要,则应在Exists子查询中应用mediaCategoryId约束。

相关问题