Web Api IEnumerable 顺序

Web Api IEnumerable order

短版:

当通过 GET 检索数据时,已排序的列表失去了正确的顺序。

长版:

有问题的函数包含 3 个步骤:

  1. 使用 dapper 加载数据
  2. 将数据映射到不同的列表
  3. Return Ok(models)

1) 小巧玲珑加载

这里我们使用小巧的查询加载一些数据。查询是基本的,采用以下形式:

SELECT * FROM tableA A 
JOIN tableB B on A.Id = B.Id 
ORDER BY A.Date DESC 
OFFSET @X ROWS
FETCH NEXT @Y ROWS ONLY

使用一些单元测试,我们可以看到我们从 transaction.Query<ModelA>(theQuery).ToList() 收到的数据排序正确,符合我们的预期。

2) 映射到不同型号

这一步基本就是return modelAs.Select(x => new ModelB(x.PropA, x.PropB)).ToList()

3) 网页 Api

最后我们简单地在我们的控制器中用 this.Ok(modelBs) 响应请求。

控制器动作大致如下所示:

[HttpGet]
[Route("the/resource")]
public IHttpActionResult LoadListOfResources(int pageNumber, int numberOfItems)
{
    var items = this.service.LoadMappedModels(pageNumber, numberOfItems);

    return this.Ok(items);
}

我们的问题是数据到达客户端时不再按日期 DESC 排序。这只发生在我们的生产和 QA 环境中。本地至少3台不同的机器都没有出现这个问题(会不会是网络相关?)。

通过单元和集成测试,我们已经验证数据顺序在我们称为 Ok(models) 之前是正确的。会不会是序列化问题?

在这一点之后,我们已经用 Android、iOS 和 Postman 客户端验证了序列化数据没有以正确的顺序表示数据。

我们知道 IEnumerable<> 接口不对顺序做出任何保证,但是,我们假设只要底层实现(List<> 在这种情况下)确实保证顺序,一切都应该没事。

任何关于这是如何发生的帮助或理论将不胜感激。 尽管我们认为我们已经通过单元测试排除了一些步骤(如 Dapper 加载程序),但我们对任何想法持开放态度。

网络不会重新排序您的响应,因此您可以排除与网络相关的问题。
序列化不会对列表中的项目重新排序,因为 - 正如您已经注意到的 - 被序列化的对象保证了项目的稳定顺序。所以,你可以排除序列化。

这让您只有一个选择:数据不是按照您期望的顺序来自数据库。
这可能是由于不同环境之间的文化差异,无论是在数据库中还是在您的应用程序中。
验证这确实是不正确排序的原因的最简单方法是简单地记录您从数据库中获得的结果,然后再进一步处理它。将其记录到文件并比较环境之间的结果。