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

meh*_*cek 6 c# nhibernate hql fluent-nhibernate c#-4.0

我使用NHibernate 3.3.1和FluentNhibernate 1.3进行数据层.

我有以下实体:

在此输入图像描述

数据库图: 在此输入图像描述

我需要一种方法来获取产品媒体的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 
Run Code Online (Sandbox Code Playgroud)

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

  1. session .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中的
    会话.查询<ProductEntity>()from m in p.MediaList
    from c in m.MediaCategoryList
    where c.Id == 23
    select p).Fetch(x => 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

Dan*_*ing 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();
Run Code Online (Sandbox Code Playgroud)

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

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

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