在我的应用程序中,有一个问题部分,允许提出问题和回应。类似于(伪代码,因为它实际上是从Entity Framework生成的)之类的
class Response
{
string Author;
string Comment;
DateTime Date;
}
class Issue
{
IEnumerable<Response> Responses;
}
我们有一个摘要页面,我们只想显示最后两个响应。我试过这样的linq查询:
from issue in db.Issue
let responses = from response in issue.Responses orderby response.Date
select new
{
Issue = issue,
Question = responses.FirstOrDefault(),
Answer = responses.Skip(1).FirstOrDefault()
}
但是这给了我一个错误,就是“跳过”只能在有序集合上使用。我检查了responses
,它是一个IOrderedEnummerable。我以为问题可能是它是Enumerable而不是IOrderedQueryable,并且看到发生这种情况是因为issue.Response是一个集合,所以我将let语句改为:
let response = from response in db.Responses where response.IssueId = issue.ID // etc.
但是这不能解决问题(但是响应确实变成了IOrderedQueryable),所以我不太确定为什么实体在这里不接受跳过。如果我将跳过语句放在let
语句中,则它可以正常工作(但是我无法得到第一个响应)。只能通过在使用该语句之前将其一部分放入变量中来出现问题。
答案 0 :(得分:1)
这里的问题是:EF如何/应该将您的查询转换为SQL语句?没有与Skip(1)类似的直接SQL。只需尝试用SQL编写查询,您就会明白我的意思。
如果您想要一个“简单”的解决方案,则只需从数据库中获取所有响应并在代码中标识所需的响应即可。
如果要最大程度地减少从数据库读取的数据,解决方案的范围可能从创建视图到编写存储过程再到更改表,以便表可以更好地反映应用程序中的数据模型。
答案 1 :(得分:0)
我不太确定这是怎么回事,但是这可能会更简单吗?
var theResponse = db.Issue.Select(i => new {
Issue = i,
Question = i.Responses.FirstOrDefault(),
Answer = i.Responses.OrderBy(r => r.Date).Skip(1).FirstOrDefault()
});
但这也很奇怪,因为您将获得一个完整的Issue
对象及其所有属性,包括Reponse
对象,并将其重新填充为Issue
属性您所有Response
对象旁边的动态类型...