c# - 验证 API 中返回的行数
问题描述
我有一个从请求中获取模型的 API。它将其转移到一个小型存储过程。该 SP 通过使用模型的一些参数来选择一些记录。它将匹配的记录作为对象列表返回。最后控制器返回响应。
简化示例:
public IHttpActionResult Get([FromBody]TestModel testModel)
{
var responseList = _testService.GetResponse(testModel);
return Ok(responseList );
}
API 一次不应返回超过 500 条记录。如果我们有更多,API 应该返回错误:“您的请求将返回超过 500 条记录”。
为检索到的记录数量添加验证的最佳解决方案是什么?
- 两个具有相同条件的选择和连接,但其中一个只返回
count(*)
? - 还是将所有数据返回给应用程序,然后在那里进行计数?
- 或者是其他东西?
解决方案
通常,当您使用 REST API 时,有太多方法可以做到这一点。
方法#1:
一种是在 SQL 级别,您需要将分页参数传递给您的 sql 逻辑,例如
public int PageNumber { get; set; } = 1;
private int PageSize = 500;
因此,您可以选择并跳过所需的元素数量。这样做有什么好处?您可以在 SQL 查询中添加一些执行计划,查看缺少哪些索引,您可以主要在 SQL 端优化您的查询。DBA 通常在大型组织中负责这些方法。
方法#2
您仍然可以从后端编写查询,至少这个很简单,它将在 SQL 服务器端执行,下面是您可以使用的扩展方法。
public static IQueryable<T> PageBy<T>(this IQueryable<T> query, int skipCount, int maxResultCount)
{
if (query == null)
{
throw new ArgumentNullException("query");
}
return query.Skip(skipCount).Take(maxResultCount);
}
方法#3:
将数据放入内存(在这种情况下将在服务器端执行,而不是在 SQL 服务器中)并从那里进行分页。您唯一需要做的就是调用 ToList() ,这将实现您的查询并将其带入内存,您可以在其中使用与方法 #2相同的想法。
方法#4:
此示例将适用于 .Net Core,但肯定有一个版本的包可以为 .NetFramework 做同样的事情。使用 OData 块包
Install-Package Microsoft.AspNetCore.OData
Add EnableQueryAttribute
and pass ODataQueryOptions<TestModel> options
, Odata 使用了一些扩展方法IQueryble
[EnableQuery]
public IHttpActionResult Get(ODataQueryOptions<TestModel> options)
{
//this should return an IQueryble<T>
var responseList = _testService.GetResponse(testModel);
var ret= options.ApplyToWithDefaultTop(responseList, ignoreQueryOptions);
return Ok(ret);
}
这是我的扩展方法,用于应用默认的元素计数
public static IQueryable ApplyToWithDefaultTop<T>(this ODataQueryOptions<T> options,
IQueryable<T> query, AllowedQueryOptions ignoreQueryOptions)
{
if (options.Top == null)
{
//this is the default
query = query.Take(500);
}
//odata extension method
return options.ApplyTo(query, ignoreQueryOptions);
}
这将与方法 #2做同样的事情,但您不必担心参数模型,它们是 Odata 语法的一部分,例如,这里我返回该资源的 40 个元素并跳过前 2 页.
https://localhost:44335/api/weather_forecast?$top=40&$skip=2
只需添加 4 行代码,您就可以将 Odata 语法放在您的 API 之上,在您的 Configure 方法中
app.UseMvc(routerBuilder =>
{
routerBuilder.EnableDependencyInjection();
//adding MaxTop from appsettings with a value of 100
//routerBuilder.Select().OrderBy().Filter().Count().MaxTop(Configuration.GetValue<int>("Odata:MaxTop"));
routerBuilder.Expand().Select().Count().OrderBy().Filter().MaxTop(Configuration.GetValue<int>("500"));
});
并ConfigureServices
添加services.AddOData();
有关更多参考资料,请参阅这篇文章:OData 文章
推荐
如果您的 API 超过 500,您不应该向客户端抛出错误,只需给他前 500 此外,您可以传递 PageSize 并验证该数字,而无需进入您的数据库并返回错误以防万一您仍然想去用这种方法。当您可以验证输入时,不要让应用程序失败。您也可以使用 FluentValidation nugget 包来验证您的DTOs
希望这可以帮助
推荐阅读
- mobx - MobX decorating a class causes function to throw TypeError
- jquery - 如何使用 Jquery 全局触发 Angular 的 ModelChange?或者如何使用 Jquery 通知角度模型更改?
- python-3.x - 使用tabula将表格从pdf导入python时出现问题
- parse-platform - 我试图使用 parse sdk for flutter 执行组合查询,但我不知道该怎么做
- javascript - 为什么这个 jQuery.animate() 函数不改变可见性?
- windows - Apache Zeppelin 在 Windows 上没有任何错误启动
- docker - Cloudbuild + lerna:正确的使用方法
- java - Hashmap updating for all keys if value is updated for a particular key
- python - 将日文字符解码为 Base64
- artifactory - Pip install 为 Artifactory 上传的包返回“找不到满足要求的版本”