可以在c#linq中的查询表达式中使用,而不是使用.Take(x)?

时间:2008-10-31 16:25:15

标签: c# linq linq-to-sql

我正在尝试编写一些生成SQL的LINQ To SQL代码,如

SELECT t.Name, g.Name
FROM Theme t
INNER JOIN (
    SELECT TOP 5 * FROM [Group] ORDER BY TotalMembers
) as g ON t.K = g.ThemeK

到目前为止我已经

var q = from t in dc.Themes 
join g in dc.Groups on t.K equals g.ThemeK into groups 
select new { 
    t.Name, Groups = (from z in groups orderby z.TotalMembers select z.Name )
};

但是我需要做一个top / take on ordered groups子查询。根据VB中的http://blogs.msdn.com/vbteam/archive/2008/01/08/converting-sql-to-linq-part-7-union-top-subqueries-bill-horst.aspx,我可以在最后添加TAKE 5,但是我无法在c#中使用这种语法。你如何在c#中使用take语法?

编辑:PS添加。最后使用(5)会使其运行大量单个查询

编辑2:我对上述SQL的意图略有错误,但问题仍然存在。 问题在于,如果在查询中使用扩展方法,如.Take(5),LinqToSql会运行大量SQL查询而不是单个查询。

3 个答案:

答案 0 :(得分:4)

第二个答案,现在我重读原来的问题。

您确定您显示的SQL实际上是否正确?它不会给出每个主题中的前5个组 - 它将匹配前5个组整体的每个主题。

简而言之,我怀疑如果您使用以下内容,您将获得原始SQL:

var q = from t in dc.Themes 
join g in dc.Groups.OrderBy(z => z.TotalMembers).Take(5)
  on t.K equals g.ThemeK into groups 
select new { t.Name, Groups = groups };

但我认为这不是你真正想要的......

答案 1 :(得分:2)

只需括起查询表达式并调用Take on it:

var q = from t in dc.Themes 
join g in dc.Groups on t.K equals g.ThemeK into groups 
select new { t.Name, Groups = 
       (from z in groups orderby z.TotalMembers select z.Name).Take(5) };

事实上,查询表达式并不能让事情变得更简单 - 您也可以直接调用OrderBy:

var q = from t in dc.Themes 
join g in dc.Groups on t.K equals g.ThemeK into groups 
select new { t.Name, Groups = groups.OrderBy(z => z.TotalMembers).Take(5) };

答案 2 :(得分:1)

这是原始查询的忠实翻译。这不应该产生重复的往返。

var subquery =
  dc.Groups
  .OrderBy(g => g.TotalMembers)
  .Take(5);

var query =
  dc.Themes
  .Join(subquery, t => t.K, g => g.ThemeK, (t, g) => new
  {
    ThemeName = t.Name, GroupName = g.Name
  }
  );

问题中的往返是由groupjoin(加入)引起的。 LINQ中的组具有层次结构。 SQL中的组具有行/列形状(分组键+聚合)。为了使LinqToSql从行/列结果中填充其层次结构,它必须使用组的密钥单独查询子节点。只有当孩子在聚合之外使用时才会这样做。