let子查询中的跳过跳过方法

时间:2018-11-23 18:17:37

标签: c# entity-framework

在我的应用程序中,有一个问题部分,允许提出问题和回应。类似于(伪代码,因为它实际上是从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语句中,则它可以正常工作(但是我无法得到第一个响应)。只能通过在使用该语句之前将其一部分放入变量中来出现问题。

2 个答案:

答案 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对象旁边的动态类型...