我正在尝试编写一些生成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查询而不是单个查询。
答案 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从行/列结果中填充其层次结构,它必须使用组的密钥单独查询子节点。只有当孩子在聚合之外使用时才会这样做。