gpt4 book ai didi

c# - 我可以让这个 Linq to EF 更有效率吗?

转载 作者:太空宇宙 更新时间:2023-11-03 14:10:10 24 4
gpt4 key购买 nike

我有一个设计,我们存储给定用户对脚本问题的答案。一个脚本可以有很多问题,每个问题可以由给定用户多次回答。

MS SQL 表看起来(删除额外的细节)或多或少像:

-Scripts
ScriptId int (PK, identity)

-ScriptQuestions
ScriptId int (PK)
QuestionId int (PK)

-Questions
QuestionId int (PK, identity)
QuestionText varchar

-Answers
AnswerId int (PK, identity)
QuestionId int
UserId int
AnswerText varchar

我想查询此数据库中的给定脚本和给定用户,并获取所有问题和为每个问题提供的最后答案(如果有)。在 T-SQL 中我会做这样的事情:

SELECT 
sq.QuestionId,
q.QuestionText,
la.AnswerText
FROM
ScriptQuestions sq
ON s.ScriptId = sq.ScriptId
INNER JOIN Questions q
ON sq.QuestionId = q.QuestionId
LEFT OUTER JOIN (
SELECT
QuestionId,
AnswerText
FROM Answers
WHERE AnswerId IN (
SELECT
MAX(AnswerId) LastAnswerId
FROM Answers
WHERE UserId = @userId
GROUP BY QuestionId
)
) la
ON q.QuestionId = la.QuestionId
WHERE
sq.ScriptId = @scriptId

(未经测试,但我认为它接近我会做的)

我在 MVC 3 应用程序上使用 LinqToEF,为了获得这些结果,我使用了:

        var questions = from sq in script.ScriptQuestions
select new QuestionsAnswers
{
QuestionId = sq.QuestionId,
QuestionText = sq.Question.QuestionText,
LastAnswer = sq.Question.Answers
.Where(a => a.UserId == userId)
.OrderByDescending(a => a.AnswerId)
.Select(a => a.AnswerText)
.FirstOrDefault()
};

我确实得到了相同的结果,但是当我从 VS 2010 运行 Intellitrace 探查器时,我可以看到 linq 将其转换为为脚本上的每个问题发送一个 SELECT 语句,然后发送另一个 SELECT 声明每个答案。因此,如果脚本有 20 个问题,它将至少查询数据库 40 次,而不是像上面那样只发送一条 SQL 语句。

我试图改变我创建 LinqToEF 语句的方式,但我无法克服 n 个 SELECT 语句问题。

这不可能是正确的方法,是吗?

最佳答案

我的猜测是您的查询使用 LINQ to 内存中的对象并结合导航属性的延迟加载,因为您的查询以 script.ScriptQuestions 开头,这显然不是 IQueryable。因此,集合在内存中迭代,对于每个条目,您都可以访问 sq.Questionsq.Question.Answers 导航属性。如果每次访问这些属性时都启用延迟加载,则会向数据库发出新查询以填充属性。您对 sq.Question.Answers 集合的过滤是在内存中对整个集合执行的。

您可以尝试通过以下方式进行更改:

    var questions = from sq in context.ScriptQuestions
where sq.ScriptId == script.ScriptId
select new QuestionsAnswers
{
QuestionId = sq.QuestionId,
QuestionText = sq.Question.QuestionText,
LastAnswer = sq.Question.Answers
.Where(a => a.UserId == userId)
.OrderByDescending(a => a.AnswerId)
.Select(a => a.AnswerText)
.FirstOrDefault()
};

这应该只是一个单一的数据库查询,因为现在它是 LINQ to Entities with IQueryable

关于c# - 我可以让这个 Linq to EF 更有效率吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8083782/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com