[英]Database query returning only the first element of the data base as the same instance for all, in ASP.NET MVC Core 6
[英]ASP.NET Core API only returning first result of list
我创建了一个团队 web api 控制器并尝试调用 GET 方法来获取数据库中所有团队的 json 结果。 但是当我拨打电话时,我只让第一个团队回到 json 中,但是当我在 return 语句上设置断点时,它包含所有 254 个团队以及所有游戏。
这是我正在处理的两个模型:
public class Team
{
public string Id { get; set; }
public string Name { get; set; }
public string Icon { get; set; }
public string Mascot { get; set; }
public string Conference { get; set; }
public int NationalRank { get; set; }
public List<Game> Games { get; set; }
}
public class Game
{
public string Id { get; set; }
public string Opponent { get; set; }
public string OpponentLogo { get; set; }
public string GameDate { get; set; }
public string GameTime { get; set; }
public string TvNetwork { get; set; }
public string TeamId { get; set; }
public Team Team { get; set; }
}
当我这样做时:
[HttpGet]
public async Task<List<Team>> Get()
{
var teams = await _context.Teams.ToListAsync();
return teams;
}
我得到了所有 254 个团队,但 Game 属性为空,因为 EF Core 不支持延迟加载。 所以我真正想做的是像这样添加 .Include() :
[HttpGet]
public async Task<List<Team>> Get()
{
var teams = await _context.Teams.Include(t => t.Games).ToListAsync();
return teams;
}
这将返回第一场比赛的第一支球队,但没有别的。 这是json:
[
{
"id": "007b4f09-d4da-4040-be3a-8e45fc0a572b",
"name": "New Mexico",
"icon": "lobos.jpg",
"mascot": "New Mexico Lobos",
"conference": "MW - Mountain",
"nationalRank": null,
"games": [
{
"id": "1198e6b1-e8ab-48ab-a63f-e86421126361",
"opponent": "vs Air Force*",
"opponentLogo": "falcons.jpg",
"gameDate": "Sat, Oct 15",
"gameTime": "TBD ",
"tvNetwork": null,
"teamId": "007b4f09-d4da-4040-be3a-8e45fc0a572b"
}
]
}
]
当我在 return 语句上设置断点时,它显示有 254 个团队,每个团队都正确填充了他们的游戏......但 json 结果没有反映。 这是一张图片:
我尝试同步和异步执行此操作,但得到相同的结果。 你知道为什么我在 json 中只得到一个结果,但在断点处它有所有结果吗?
将此添加到Startup.cs
的public void ConfigureServices(IServiceCollection services)
方法:
services.AddMvc().AddJsonOptions(options => {
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
讨论了这个问题https://github.com/aspnet/Mvc/issues/4160和https://github.com/aspnet/EntityFramework/issues/4646也见循环参考
值得注意的是,如果您像使用内联JsonSerializerSettings
选项那样控制 json 输出,
[HttpGet]
public async Task<IActionResult> Get([FromForm]bool strip_nulls = true)
{
var teams = await _context.Teams.Include(t => t.Games).ToListAsync();
return Json(teams, new JsonSerializerSettings() {
NullValueHandling = strip_nulls ? NullValueHandling.Ignore : NullValueHandling.Include
});
}
简单地提出@adeam-caglin 的建议解决方案,这在方法上没有错,是行不通的。 您还必须在退货中设置该设置。 例如。
[HttpGet]
public async Task<IActionResult> Get([FromForm]bool strip_nulls = true)
{
var teams = await _context.Teams.Include(t => t.Games).ToListAsync();
return Json(teams, new JsonSerializerSettings() {
NullValueHandling = strip_nulls ? NullValueHandling.Ignore : NullValueHandling.Include,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
}
它基本上是空的,而不是添加到您在Startup.cs
上设置的设置。 这也为您提供了一个路线图,不要全局更改您的输出,而是逐案进行。
我还想花点时间澄清一下当您使用ReferenceLoopHandling.Ignore
时会发生什么,您要求从消防软管中喝水,但希望它是受控的流量。 如果您有一个高度发达的建模,那么您可能会有一个集合,您认为您将在其中获得预期的实体及其子列表,但是如果这些列表项也有子项或其他父项,那么您将加载它们。 让我们说你有
Teams>Players>Contacts
Games>Teams
这会产生大量的 json 嵌套返回。 我本来想要一个扁平的Game>Teams
但最终会得到Games>Teams>Players
。 这是一个简单的示例,但很容易看出如何从几 KB 的数据转到永无止境的循环,从而扼杀了使用结果的客户端。
这意味着你需要控制自己的流动。 要获得预期的更平坦的 json 返回,您还需要在.Include(x => x.Games)
上合并.AsNoTracking()
.Include(x => x.Games)
作为一个非常简单的示例,您需要执行以下操作:
[HttpGet]
public async Task<IActionResult> Get([FromForm]bool strip_nulls = true)
{
var teams = _context.Teams.AsQueryable();
teams = teams.Include(t => t.Games).AsNoTracking();
Teams _return = await teams.ToListAsync();
return Json(_return, new JsonSerializerSettings() {
NullValueHandling = strip_nulls ? NullValueHandling.Ignore : NullValueHandling.Include,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.