6

我正在使用 NHibernate 3.3.1 和 FluentNhibernate 1.3 作为数据层。

我有以下实体:

在此处输入图像描述

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

我需要一种按产品媒体的媒体类别获取产品的方法。我希望 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. session .QueryOver< ProductEntity >()...
    我已经尝试过Inner.JoinQueryOver< .. >().Fetch.Eager...但我无法获取所有子实体。

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

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

  4. (from p in session.Query< 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<>()我们可以用orsession.CreateCriteria,或处理这种情况QueryOver吗?

4

1 回答 1

8

对于您的查询的直接翻译...

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允许我们通过 Media 深入挖掘类别,并且它还急切地获取数据。

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

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

于 2013-08-21T22:07:47.330 回答