2011-04-14 54 views
0

此查询需要一组评论,然后在tblCommentVotes表中统计他们的upvotes和downvotes。Linq可以优化这些子查询吗?

目前,它通过select子语句形式的select语句对这些进行计数。如果它在主要查询中处于某种组中,这会更有效吗?如果可以的话,任何人都可以告诉我如何做到这一点,因为我无法弄清楚如何做到这一点。

// Get comments 
var q = (
    from C in db.tblComments 
    where 
     C.CategoryID == Category && 
     C.IdentifierID == Identifier 
    join A in db.tblForumAuthors on C.UserID equals A.Author_ID 
    orderby C.PostDate descending 
    select new 
    { 
     C, 
     A.Username, 
     UpVotes = (from V in db.tblCommentVotes where V.CommentID == C.ID && V.UpVote == true select new { V.ID }).Count(), 
     DownVotes = (from V in db.tblCommentVotes where V.CommentID == C.ID && V.UpVote == false select new { V.ID }).Count() 
    } 
) 
.Skip(ToSkip > 0 ? ToSkip : 0) 
.Take(ToTake > 0 ? ToTake : int.MaxValue); 
+1

你是什么意思的“优化”?更高效的SQL?更少/更优雅的代码?如果SQL是你想要的,它可能有助于发布生成的SQL。 – Brook 2011-04-14 23:17:33

+0

要优化SQL,请查看索引,而不是语言。那么,你确切的模式是什么? – 2011-04-14 23:45:29

回答

3

你需要做的是做一个左外连接在查询表达式的db.tblCommentVotes的,造成可能有可能没有commentVotes?

当你有这个,你应该能够执行一个查询,以获得您的结果。

这可能是这样的:

var q = (
    from C in db.tblComments 
    where 
     C.CategoryID == Category && 
     C.IdentifierID == Identifier 
    join A in db.tblForumAuthors on C.UserID equals A.Author_ID 
    // the following two lines are the left outer join thing. 
    join voteTemp in db.tblCommentVotes on voteTemp.CommentID equals C.ID into voteJoin 
    from vote in voteJoin.DefaultIfEmpty() 
    orderby C.PostDate descending 
    group C by new { Comment = C, Username = A.Username } into g 
    select new 
    { 
     g.Key.Comment, 
     g.Key.Username, 
     UpVotes = g.Count(x => x.UpVote), 
     DownVotes = g.Count(x => !x.UpVote) 
    } 
) 
.Skip(ToSkip > 0 ? ToSkip : 0) 
.Take(ToTake > 0 ? ToTake : int.MaxValue); 

这是未经测试,甚至可能没有编译,但我想应该是这样的。

1
db.tblComments.Where(c => c.CategoryID == Category && c.IdentifierID == Identifier) 
       .Join(db.tblForumAuthors, c => c.UserID, a => a.Author_ID, 
        (c, a) => 
        new 
        { 
         CommentID = c, 
         AuthorName = a.UserName, 
         UpVotes = c.Join(db.tblCommentVotes, c => c.CommentID 
                  v => v.CommentID, 
                  (c, v) => v).Count(v => v.UpVote) 
         DownVotes = c.Join(db.tblCommentVotes, c => c.CommentID 
                   v => v.CommentID, 
                   (c, v) => v).Count(v => v.DownVote) 
        }); 
+0

这不会导致选择n + 1场景吗?第二次? – 2011-04-14 23:36:18

+0

嗯...是的。你的'GroupBy'更好。 – Femaref 2011-04-14 23:53:26

1

要优化它是最好的首先要衡量。

  • 尝试,使用类似LinqPad查看生成的SQL
  • 然后使用SQL Server Management Studio中看到的查询计划是SQL

或:

  • 尝试运行代码并查看SQL跟踪告诉您发生了什么

如果没有数据库,猜测该Linq是否会导致单个查询或多个查询来计算UpVotes和DownVotes是非常困难的(但很有趣)。我的猜想是这样计算UpVotes和DownVotes可能会非常昂贵 - 它可能会导致每个评论2个附加查询。