Context
Я создаю simple . NET Core API и у меня возникли проблемы с возвратом правильных данных из моих контроллеров. Я предвидел необходимость использовать DTO для управления тем, какие данные отправляются в и из API, но я не уверен, что мои отношения EF Core настроены правильно. Для всего oop меня бросает то, что дочерние объекты в моих моделях возвращают ноль - я объясню дальше. У меня есть две модели домена: Player и Match . В каждом матче четыре игрока, и я думаю, что для одного и того же стола потребуется создать четыре внешних ключа. База данных SQL, которую генерирует EF Core, выглядит так, как я ее представлял - я включил снимок экрана для большего контекста. Я могу просто создавать объекты Player, используя метод API POST. Однако когда я создаю объект Match, используя Player Guids (как показано ниже), запрос вновь созданного объекта Match из базы данных не возвращает объект Player в JSON, как я надеялся; MatchController возвращает Руководства игрока, но без информации об игроке. В конечном счете, я хотел бы последовательно отображать данные об игроках для каждого из четырех игроков в матче , но я не уверен, какие изменения в моих моделях или Fluent API потребовались бы для меня, чтобы добиться этого. Я планирую использовать AutoMapper для сопоставления объектов модели домена с объектами модели DTO в будущем, но это текущее затруднение кажется чем-то, что я должен сгладить в первую очередь. Я был бы более чем рад предоставить больше информации, если есть что-то еще, что позволит лучше помочь! Любая помощь будет искренне и высоко ценится! Заранее спасибо!
Примечание. Меня не волнует наличие коллекции соответствий в моей модели проигрывателя - я включил ее только потому, что считал необходимым создать ограничения внешнего ключа в 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 (Свободный 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-запросы
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
}
]