我在Entity Framework中有这个查询:
_context.Onlines
.Where(x => x.Date >= startDate.Date && x.Date <= endDate.Date && x.User.Id == userId)
.OrderByDescending(x => x.Date)
.Skip((int)size * (page - 1))
.Take((int)size)
.ToList();
你怎么看,我正在用“Skip”和“Take”进行分页搜索,我需要享受这个查询来计算这个查询的总结果(不仅是分页的部分计数),还有将结果,同一请求中的所有内容返回给数据库。
我需要这个来计算视图中的分页。
答案 0 :(得分:3)
你可以这样做:
var query = _context.Onlines
.Where(x => x.Date >= startDate.Date && x.Date <= endDate.Date && x.User.Id == userId);
// getting just count
int totalCount = query.Count();
// and then getting items itself
var items = query
.OrderByDescending(x => x.Date)
.Skip((int)size * (page - 1))
.Take((int)size)
.ToList();
它将根据原始条件生成两个SQL查询。一个用于计数,第二个用于项目。
答案 1 :(得分:1)
您可以使用Entity Framework Extended在一个事务中执行此操作。这是一个你可以找到的nuget包。我将引导您完成我们为服务器端分页所做的决定。
我们需要返回的列表和总记录数。 KeyValuePair<int, List<WhateverReturnModel>>
应该很好用。
让我们来看看我们现在应该采取的措施。
创建一个分页请求模型,其默认PageNumber为x,PageSize为z。
public class PagedRequest
{
private int? _pageNumber;
private int? _pageSize;
private int? _pageSkip;
public int PageNumber
{
get { return this._pageNumber ?? 1; }
set { this._pageNumber = value; }
}
public int PageSize
{
get { return this._pageSize ?? 15; }
set { this._pageSize = value; }
}
}
设置返回方法以处理KeyValuePair
结果
protected KeyValuePair<int, List<T>> PagedResult<T>(int count, List<T> list)
{
return new KeyValuePair<int, List<T>>(count, list);
}
将这些添加到需要分页的端点
public KeyValuePair<int, List<WhateverModel>> DoSomething([FromUri] PagedRequest paged)
{
var records = yourContext.YourTable.Where(t => true);
var count = records.FutureCount() // this will not execute right away.. only when it is finally called
var data = yourContext.YourTable
.Where(t => t.Something)
.OrderBy(i => i.Anything)
.Skip(this.PageSkip(paged.PageNumber, paged.PageSize))
.Take(paged.PageSize)
.Future() // again this will not execute right away
return this.PagedResult(count, data.ToList()); // now both queries will execute in one call
}
使用分页方法的API方法。
public HttpResponseMessage DoAnotherThing()
{
var test = new WhateverClass.DoSomething();
return this.Paged(test);
}
然后,您可以编写方法Paged()
,它将返回KeyValuePair
值作为响应内容,您可以为总计数添加标题。像这样......
protected HttpResponseMessage OkPaged<T>(KeyValuePair<int, List<T>> content)
var response = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ObjectContent<Object>(content.Value, this.GetConfiguration().Formatters.JsonFormatter)
};
response.Headers.Add("x-paging-total", content.Key.ToString());
return response;
}
答案 2 :(得分:1)
在单个查询中执行这两个操作不会产生任何性能优势。但是,可以使用nuget包EntityFrameworkPaginate以优雅的方式捕获分页数据。它的工作方式是你设置动态过滤和排序,你将得到一个Page对象作为结果,它将产生结果和元数据。 (CurrentPage,PageCount,PageSize,RecordCount和Results)。
首先,您需要设置过滤器。在你的情况下,你有一个条件。在基于不同条件的多个where子句的情况下,您可以将这些过滤器添加到过滤器对象。
var filters = new Filters<Onlines>();
filters.Add(true, x => x.Date >= startDate.Date
&& x.Date <= endDate.Date && x.User.Id == userId);
接下来,您需要按以下方式设置订单。在你的情况下,只有一个,但Sorts类也可以处理动态排序。
var sorts = new Sorts<Onlines>();
sorts.Add(true, x => x.Date, true);
现在要最终获取您的分页数据,您需要在dbset上调用扩展方法paginate。
Page<Onlines> paginatedData = context.Employees.Paginate(page, size, sorts, filters);
Voila,您将获得包含所有必需元数据的分页数据。这提供了一种干净的方法,在您进行动态过滤和排序时非常有用。您可以查看详细文章here。