我正在构建简单 .NET Core API,并且从我的控制器返回正确的数据时遇到了一些麻烦。我预见到必须使用DTO来管理向API发送和从API发送的数据,但是我不认为自己的EF Core关系配置正确。让我陷入循环的是我模型中的子对象正在返回null-我将进一步解释。我有两个域模型,Player和Match。每场比赛都有4名选手,我相信这需要在同一张桌子上创建4个外键。 EF Core生成的SQL数据库看上去就像我所设想的一样-为了更多的上下文,我也包括了screenshot。我可以使用API POST方法创建Player对象。但是,当我使用播放器指南(如下所示)创建Match对象时,从数据库中查询新创建的Match对象并不会像我希望的那样以JSON返回Player对象。 MatchController返回玩家指南,但没有玩家信息。最终,我想一致地显示比赛中四个球员中每个球员的球员数据,但是我不确定要实现此目标需要对模型或Fluent API进行哪些更改。我确实计划将来使用AutoMapper将域模型对象映射到DTO模型对象,但是这种当前的困境似乎让我首先需要解决。如果还有其他可以提供更好帮助的信息,我将非常乐意提供更多信息!任何和所有帮助将由衷地感谢!预先感谢!
注意:我不在乎在Player模型中包含Matchs的集合-我只包含其中的一个,因为我认为在Entity Framework Core中构建外键约束是必要的
Player.cs(域模型)
public class Player
{
[Key]
public Guid Id { get; set; }
[Required]
public string Name { get; set; }
public double Rating { get; set; }
public DateTime Created { get; set; }
public DateTime Updated { get; set; }
public ICollection<Match> MatchesOne { get; set; }
public ICollection<Match> MatchesTwo { get; set; }
public ICollection<Match> MatchesThree { get; set; }
public ICollection<Match> MatchesFour { get; set; }
}
Match.cs(域模型)
public class Match
{
[Key]
public Guid Id { get; set; }
[Required]
public int TeamOneScore { get; set; }
[Required]
public int TeamTwoScore { get; set; }
public DateTime Created { get; set; }
public DateTime Updated { get; set; }
public Guid PlayerOneId { get; set; }
public Guid PlayerTwoId { get; set; }
public Guid PlayerThreeId { get; set; }
public Guid PlayerFourId { get; set; }
public Player PlayerOne { get; set; }
public Player PlayerTwo { get; set; }
public Player PlayerThree { get; set; }
public Player PlayerFour { get; set; }
}
ApplicationDbContext.cs(Fluent API)
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Player>()
.Property(p => p.Rating)
.HasDefaultValue(1000);
modelBuilder.Entity<Player>()
.Property(p => p.Created)
.HasDefaultValueSql("GETDATE()");
modelBuilder.Entity<Player>()
.Property(p => p.Updated)
.HasDefaultValueSql("GETDATE()");
modelBuilder.Entity<Match>()
.Property(m => m.Created)
.HasDefaultValueSql("GETDATE()");
modelBuilder.Entity<Match>()
.Property(m => m.Updated)
.HasDefaultValueSql("GETDATE()");
modelBuilder.Entity<Player>()
.HasMany(p => p.MatchesOne)
.WithOne(m => m.PlayerOne)
.HasForeignKey(m => m.PlayerOneId)
.OnDelete(DeleteBehavior.NoAction);
modelBuilder.Entity<Player>()
.HasMany(p => p.MatchesTwo)
.WithOne(m => m.PlayerTwo)
.HasForeignKey(m => m.PlayerTwoId)
.OnDelete(DeleteBehavior.NoAction);
modelBuilder.Entity<Player>()
.HasMany(p => p.MatchesThree)
.WithOne(m => m.PlayerThree)
.HasForeignKey(m => m.PlayerThreeId)
.OnDelete(DeleteBehavior.NoAction);
modelBuilder.Entity<Player>()
.HasMany(p => p.MatchesFour)
.WithOne(m => m.PlayerFour)
.HasForeignKey(m => m.PlayerFourId)
.OnDelete(DeleteBehavior.NoAction);
}
PlayerController.cs
[HttpGet]
public async Task<ActionResult<IEnumerable<Player>>> GetPlayers()
{
return await _context.Players.ToListAsync();
}
[HttpPost]
public async Task<ActionResult<Player>> PostPlayer(Player player)
{
_context.Players.Add(player);
await _context.SaveChangesAsync();
return CreatedAtAction(nameof(GetPlayer), new { id = player.Id }, player);
}
MatchController.cs
[HttpGet]
public async Task<ActionResult<IEnumerable<Match>>> GetMatches()
{
return await _context.Matches.ToListAsync();
}
[HttpPost]
public async Task<ActionResult<Match>> PostMatch(Match match)
{
_context.Matches.Add(match);
await _context.SaveChangesAsync();
return CreatedAtAction(nameof(GetMatch), new { id = match.Id }, match);
}
HTTP POST:PostPlayer(/ api / Player)请求:
{
"Name":"Mike Blart"
}
响应:
{
"id": "d3c022a2-d347-4a9a-d3ec-08d7b5480646",
"name": "Mike Blart",
"rating": 1000,
"created": "2020-02-19T14:32:48.8033333",
"updated": "2020-02-19T14:32:48.8033333",
"matchesOne": null,
"matchesTwo": null,
"matchesThree": null,
"matchesFour": null
}
HTTP POST:PostMatch(/ api / Match)请求:
{
"TeamOneScore":21,
"TeamTwoScore":13,
"PlayerOneId":"0589867f-590b-4344-d3e9-08d7b5480646",
"PlayerTwoId":"0f45247b-1fdb-404a-d3ea-08d7b5480646",
"PlayerThreeId":"f8b4e13d-0dd0-4ef5-d3eb-08d7b5480646",
"PlayerFourId":"d3c022a2-d347-4a9a-d3ec-08d7b5480646"
}
响应:
{
"id": "dfdc2f23-0786-40df-8aa7-08d7b54fd4a1",
"teamOneScore": 21,
"teamTwoScore": 13,
"created": "2020-02-19T15:24:38.7233333",
"updated": "2020-02-19T15:24:38.7233333",
"playerOneId": "0589867f-590b-4344-d3e9-08d7b5480646",
"playerTwoId": "0f45247b-1fdb-404a-d3ea-08d7b5480646",
"playerThreeId": "f8b4e13d-0dd0-4ef5-d3eb-08d7b5480646",
"playerFourId": "d3c022a2-d347-4a9a-d3ec-08d7b5480646",
"playerOne": null,
"playerTwo": null,
"playerThree": null,
"playerFour": null
}
HTTP GET:GetPlayers(/ api / Player)
[
{
"id": "0589867f-590b-4344-d3e9-08d7b5480646",
"name": "Merwin Dedrick",
"rating": 1000,
"created": "2020-02-19T14:28:44.7966667",
"updated": "2020-02-19T14:28:44.7966667",
"matchesOne": null,
"matchesTwo": null,
"matchesThree": null,
"matchesFour": null
},
{
"id": "0f45247b-1fdb-404a-d3ea-08d7b5480646",
"name": "Omar Rupaz",
"rating": 1000,
"created": "2020-02-19T14:30:04.4933333",
"updated": "2020-02-19T14:30:04.4933333",
"matchesOne": null,
"matchesTwo": null,
"matchesThree": null,
"matchesFour": null
},
{
"id": "f8b4e13d-0dd0-4ef5-d3eb-08d7b5480646",
"name": "Aaron Randolph",
"rating": 1000,
"created": "2020-02-19T14:32:38.7066667",
"updated": "2020-02-19T14:32:38.7066667",
"matchesOne": null,
"matchesTwo": null,
"matchesThree": null,
"matchesFour": null
},
{
"id": "d3c022a2-d347-4a9a-d3ec-08d7b5480646",
"name": "Mike Blart",
"rating": 1000,
"created": "2020-02-19T14:32:48.8033333",
"updated": "2020-02-19T14:32:48.8033333",
"matchesOne": null,
"matchesTwo": null,
"matchesThree": null,
"matchesFour": null
}
]
HTTP GET:GetMatches(/ api / Match)
[
{
"id": "ce06237b-a137-47bc-e0b7-08d7b5484c68",
"teamOneScore": 21,
"teamTwoScore": 13,
"created": "2020-02-19T14:33:24.1266667",
"updated": "2020-02-19T14:33:24.1266667",
"playerOneId": "0589867f-590b-4344-d3e9-08d7b5480646",
"playerTwoId": "0f45247b-1fdb-404a-d3ea-08d7b5480646",
"playerThreeId": "f8b4e13d-0dd0-4ef5-d3eb-08d7b5480646",
"playerFourId": "d3c022a2-d347-4a9a-d3ec-08d7b5480646",
"playerOne": null,
"playerTwo": null,
"playerThree": null,
"playerFour": null
}
]