实体框架分页和排序会产生意外结果

时间:2016-04-12 08:59:01

标签: asp.net .net entity-framework linq-to-entities

我目前正在构建一个ASP.NET Web应用程序搜索结果页面。我已经为用户实现了不同类型的排序,但其中一些排序产生了意想不到的结果。

无论排序类型或任何其他因素如何,都会执行这两行代码:

var resources = ctx.Resource.Where(p => p.CityAlias == city.ToLower() && p.Company.Hidden != true && p.State == 1);

FilterResources(ref resources, resourceTypeId, serviceId);

FilterResources:

private void FilterResources(ref IQueryable<Resource> allRes, int resourceType, int selectedService)
{
    allRes = allRes.Where(p => p.ResourceType_Id == resourceType && p.ResourceService.Any(x => x.Service_Id == selectedService));
}

Resource.ResourceService的类型为ICollection,它映射到同名的数据库表,外键指向Resource.Id

到目前为止一切顺利。首先是一个有效的排序示例:

private void SortResourcesByName(ref IQueryable<Resource> resources)
{
    resources = resources.OrderBy(p => p.Name);
}

然后我们处理分页:

int count = resources.Count();

var resourceList = resources.Skip((page - 1) * 10).Take(10).ToList();

这些来自实体的集合似乎是正确的并且顺序正确,但是当事情变得奇怪时,

如果我们使用不同的排序,某些页面会有重复的结果,在某些情况下,如果我浏览这些页面,我可以看到分散在列表中的重复(或更多)资源。

例如:

private void SortResourcesByPrice(ref IQueryable<Resource> resources, int serviceId)
{
    resources = resources.OrderByDescending(p => p.ResourceService.FirstOrDefault(s => s.Service_Id == serviceId).Price.Value)
        .ThenByDescending(p => p.Company.CompanyService.FirstOrDefault(c => c.ServiceId == serviceId).Price.Value);
}

如果我使用这种方式,视图的第一页是正确的,但是当我开始导航到其他页面时,我开始看到重复的结果。

查询返回的结果超过200个,分为21个页面。由于某些原因,第3页和第4页完全相同,第5页和第6页也产生相同的结果。在这些情况下,ResourceService.Price = null。

奖金古怪: 使用OrderBy()而不是OrderByDescending不会给出重复的结果

private void SortResourcesByPrice(ref IQueryable<Resource> resources, int serviceId)
{
    resources = resources.OrderBy(p => p.ResourceService.FirstOrDefault(s => s.Service_Id == serviceId).Price.Value)
    .ThenBy(p => p.Company.CompanyService.FirstOrDefault(c => c.ServiceId == serviceId).Price.Value);
}

我在这里完全失败,所以我真的很感激帮助。如果您无法理解我的示例代码或无法以其他方式理解该问题,我很乐意尝试提供更多信息。

编辑: 我想补充一点,结果/资源的数量总是相同的,无论我使用的是什么(正如它应该的那样)。

编辑2: 修正了一些数字&amp;错别字

1 个答案:

答案 0 :(得分:0)

您可以使用https://expressprofiler.codeplex.com/查看通过EF复制生成的SQL并直接在SQL Server Management Studio中粘贴sql查询并查看重复的原始位置,您可以更改查询以删除重复的条目并在搜索之后Linq负责。 你也可以把SQL放在这里