【问题标题】:How to write this Linq to NHibernate query如何编写这个 Linq to NHibernate 查询
【发布时间】:2015-04-28 09:19:45
【问题描述】:

我们有这样的实体:

public class File{
       public int Region{get;set;}
       public bool ShowLocation{get;set;}
       //Other fields are omitted
}

我想写这个查询:

    SELECT Region,SUM(CASE WHEN ShowLocation=1 THEN 1 ELSE 0 END) AS
 ShowCount,SUM(CASE WHEN ShowLocation=0 THEN 1 ELSE 0 END) AS NotShowCount
--WHERE omitted for the sake of simplicity
GROUP BY Region

出于某些原因,我想使用 Linq To Nhibernate(我们有一个复杂的过滤机制,可以生成 Expression<Func<File,bool>>

到目前为止,我找不到使用 Linq To NHibernate 实现此目的的任何方法。 以下是我的一些尝试:

条件计数:(没有例外,但它仍然计算所有行)

    Files
    .Where(whereExpression)
    .GroupBy(x=>x.Region)
    .Select(x=>new
    {
        x.Region,
        ShowCount=x.Count(f=>f.ShowLocation==1),
        NotShowCount=x.Count(f=>f.ShowLocation==0)
    });

条件总和:不支持/实现的异常

Files
.Where(whereExpression)
.GroupBy(x=>x.Region)
.Select(x=>new 
{
  x.Region,
  ShowCount=x.SUM(f=>f.ShowLocation==1?1:0),
  NotShowCount=x.SUM(f=>f.ShowLocation==0?1:0)
});

在 GROUP 之前选择:不支持/实现的异常

    Files.Where(whereExpression).Select(x=>new
    {
       x.Region,
       Show=x.ShowLocation==1?1:0,
       NotShow=x.ShowLocation==0?1:0
    })
    .GroupBy(x=>x.Region)
    .Select(x=>new 
    {
       x.Region,
       ShowCount=x.SUM(f=>f.Show),
       NotShowCount=x.SUM(f=>f.NotShow)
    });

UNION : 不支持/实现的异常

    Files
       .Where(whereExpression)
       .Where(x=>x.ShowLocation==1)
 .Select(x=>new
{
x.Region,
Show=1,NotShow=0
})
.Union(Files
 .Where(whereExpression)
.Where(x=>x.ShowLocation==0)
.Select(x=>new
{x.Region,
Show=0,
NotShow=1
}))
.GroupBy(x=>x.Region)
.Select(x=>new 
{
x.Region,
CountShow=x.Count(a=>a.Show),
CountNotShow=x.Count(a=>a.NotShow)
});

我没有其他线索。还有什么想法吗?

【问题讨论】:

    标签: c# linq nhibernate


    【解决方案1】:

    我使用了您的第二次尝试,并在 Select() 之前插入了 ToList()。结果如下所示:

    Files
    .Where(whereExpression)
    .GroupBy(x=>x.Region)
    .ToList<IGrouping<int, File>>()
    .Select(x=>new 
    {
      x.Key,
      ShowCount = x.Sum(f => f.ShowLocation == 1 ? 1 : 0),
      NotShowCount = x.Sum(f => f.ShowLocation == 0 ? 1 : 0)
    });
    

    这样,Select 被应用到 List 而不是 IQueryable。

    【讨论】:

    • 如果我找不到以任何其他方式创建查询的方法,那可能是另一种选择:) 谢谢
    • 好吧,我测试了它,结果证明这是一个非常糟糕的主意,因为它不允许您在 GroupBy 之前投影您需要的唯一列,因此它会尝试获取所有对象图,无论它们是不是延迟加载的,在我们的例子中,它会导致 SELECT N+1 :)
    【解决方案2】:

    我不知道你是否可以让它与 Linq to NH 一起使用。您可以改用 QueryOver 吗? QueryOver API 还在 where 子句中使用 Expression&lt;Func&lt;T,bool&gt;&gt;,因此您应该能够使其与现有过滤器一起工作:

                MyDto dto = null;
    
                var myDtoList = session.QueryOver<File>()
                    .Select(
                        Projections.Group<File>(x => x.Region).WithAlias(() => dto.Region),
                        Projections.Sum(
                            Projections.Conditional(
                                Restrictions.Where<File>(c => c.ShowLocation== 1),
                                Projections.Constant(1),
                                Projections.Constant(0))).WithAlias(() => dto.ShowCount),
                        Projections.Sum(
                            Projections.Conditional(
                                Restrictions.Where<File>(c => c.ShowLocation== 0),
                                Projections.Constant(1),
                                Projections.Constant(0))).WithAlias(() => dto.NotShowCount))
                    .TransformUsing(Transformers.AliasToBean<MyDto>())
                    .List<MyDto>();
    

    QueryOver 并不真正适用于匿名类型,因此您必须使用要返回的属性定义MyDto,即RegionShowCountNotShowCount

    【讨论】:

    • 不幸的是,正如我在问题中提到的那样,我担心我必须使用 Linq 来 NHibernate。
    • @Beatles1692 好的,抱歉,我以为您只想使用 Linq to Nh,因为您想重用返回 Expression&lt;Func&lt;File,bool&gt;&gt; 的过滤机制
    • 问题是QueryOver不支持Linq expressions中的一些如Any
    • 有一些方法可以为 nhibernate linq 提供程序创建自己的扩展方法。看看这个可能:codeproject.com/Articles/318177/… 并且可能尝试创建自己的扩展,即 SumWhere(x=>x.ShowLocation==1) 或类似的东西。我从未尝试过,但可能值得一试?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多