在 Linq 查询中需要帮助

Posted

技术标签:

【中文标题】在 Linq 查询中需要帮助【英文标题】:Need help in Linq Queries left Outer Join 【发布时间】:2011-08-06 22:37:55 【问题描述】:

如何在 LINQ 中编写:

SELECT 
    T.TestId,
    S.SubjectName+' >> '+T.TestName +' ('+ CONVERT(VARCHAR(10),COUNT(Q.TestId)) +')' TestData
FROM 
    Test T LEFT OUTER JOIN Subject S
    ON T.SubjectId = S.SubjectId
    LEFT OUTER JOIN Quest Q
    ON T.TestId = Q.TestId
GROUP BY 
    Q.TestId, 
    T.TestId,
    T.TestName,
    S.SubjectName
ORDER BY 
    COUNT(Q.TestId) DESC

在 LINQ 中编写 Left Outer Join & Group by 时需要帮助。

案例二:

SELECT 
    S.SubjectName,
    T.TestName,
    Q.Question,
    A.Answer,
    A.IsCorrect
FROM Ans A
    INNER JOIN Quest Q
    ON A.QuestId = Q.QuestId
    AND A.QuestId IN ( SELECT 
                            Q.QuestId
                        FROM Quest Q
                            INNER JOIN Test T
                            ON Q.TestId = T.TestId )
    INNER JOIN Subject S
    ON A.SubjectId = S.SubjectId
    INNER JOIN Test T
    ON A.TestId = T.TestId 

谢谢。

【问题讨论】:

【参考方案1】:

如果你有映射,应该很容易没有任何连接:

from test in tests
let count = test.Quests.Count()
orderby count descending
select
    new
    
        test.Id,
        TestData =
            test.Subject == null
                ? null
                : string.Format("0 >> 1 (2)", test.Subject.Name, test.Name, count)
    ;

编辑:阅读 Thomas Levesque 的回答后,我意识到这行不通,但以下应该:

var query = from test in tests
            let count = test.Quests.Count()
            orderby count descending
            select
                new
                
                    test.Id,
                    test.Name,
                    test.Subject,
                    Count = count
                ;

var results = query
    .AsEnumerable()
    .Select(
        t =>
        new
        
            t.Id,
            TestData =
            t.Subject == null
                ? null
                : string.Format("0 >> 1 (2)", t.Subject.Name, t.Name, t.Count)
        );

        results.Dump();
    

【讨论】:

【参考方案2】:

要在 Linq 中执行外连接,您需要使用 DefaultIfEmpty 扩展方法:

var query =
    from t in db.Test
    join s in db.Subject on t.SubjectId equals s.SubjectId into testSubject
    from s in testSubject.DefaultIfEmpty()
    join q in db.Quest on t.TestId equals q.TestId into testQuest
    from q in testQuest.DefaultIfEmpty()
    group by new
    
        t.TestId,
        t.TestName,
        s.SubjectName
    
    select new
    
        g.Key.TestId,
        g.Key.TestName,
        g.Key.SubjectName,
        Count = g.Count()
    ;

var results = from r in query.AsEnumerable()
              select new
              
                  r.TestId,
                  TestData = string.Format("0 >> 1 (2)", r.SubjectName, t.TestName, r.Count);
              

请注意,group by 子句中不需要同时使用 t.TestIdq.TestId,因为它们的值相同。对于最后一部分,我使用AsEnumerable,以便最终投影在内存中而不是在数据库中执行,这样就可以使用string.Format

【讨论】:

以上是关于在 Linq 查询中需要帮助的主要内容,如果未能解决你的问题,请参考以下文章

在 Linq 查询上需要一些帮助,第三级包括 where

LINQ to DataSet 查询帮助

LINQ 分组查询

LINQ 查询需要更多时间来执行

linq查询中的异步任务方法问 题在c#中返回

使用 LINQ 和实体框架在一个 SQL 查询中从多个表中提取数据