Я пытаюсь создать новую запись в своей таблице Game
, используя EF Core Code First. Он разделяет отношения один-ко-многим с Genre
, Developer
, Publisher
и Platform
.
Я использую модель представления под названием GameCreateViewModel
для Game / Create View, которая содержит Свойство Game
, а также свойства для списков выбора, которые соответствуют каждому внешнему ключу, например List<SelectListItem> Genres
.
Проблема, с которой я сталкиваюсь, заключается в том, что когда я пытаюсь создать новый Game
, это дает мне эту ошибку :
Microsoft.EntityFrameworkCore.DbUpdateException
HResult=0x80131500
Message=An error occurred while updating the entries. See the inner exception for details.
Source=Microsoft.EntityFrameworkCore.Relational
StackTrace:
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(IEnumerable`1 commandBatches, IRelationalConnection connection)
at Microsoft.EntityFrameworkCore.Storage.RelationalDatabase.SaveChanges(IList`1 entries)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IList`1 entriesToSave)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(DbContext _, Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges()
at GameSource.Data.Repositories.GameRepository.Insert(Game game) in E:\Tom\source\repos\My Projects\GameSource\GameSource.Data\Repositories\GameRepository.cs:line 35
at GameSource.Services.GameService.Insert(Game game) in E:\Tom\source\repos\My Projects\GameSource\GameSource.Services\GameService.cs:line 29
at GameSource.Controllers.GamesController.Create(GameCreateViewModel viewModel) in E:\Tom\source\repos\My Projects\GameSource\GameSource\Controllers\GamesController.cs:line 88
at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
This exception was originally thrown at this call stack:
[External Code]
Inner Exception 1:
SqlException: Cannot insert explicit value for identity column in table 'Developer' when IDENTITY_INSERT is set to OFF.
Cannot insert explicit value for identity column in table 'Genre' when IDENTITY_INSERT is set to OFF.
Cannot insert explicit value for identity column in table 'Platform' when IDENTITY_INSERT is set to OFF.
Cannot insert explicit value for identity column in table 'Publisher' when IDENTITY_INSERT is set to OFF.
Игра класс модели:
public class Game
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
public Genre Genre { get; set; }
public Developer Developer { get; set; }
public Publisher Publisher { get; set; }
public string Description { get; set; }
public Platform Platform { get; set; }
}
Жанр класс модели:
public class Genre
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
}
GameCreateViewModel :
public class GameCreateViewModel
{
public Game Game { get; set; }
public List<SelectListItem> Genres { get; set; }
public List<SelectListItem> Developers { get; set; }
public List<SelectListItem> Publishers { get; set; }
public List<SelectListItem> Platforms { get; set; }
}
Game / Create View - код только списка выбора жанра, тот же формат повторяется для других списков выбора:
@model GameSource.ViewModels.GameViewModel.GameCreateViewModel
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Game.ID" />
<div class="form-group">
<label asp-for="Game.Name" class="control-label"></label>
<input asp-for="Game.Name" class="form-control" />
<span asp-validation-for="Game.Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Game.Genre" class="control-label"></label>
<select asp-for="Game.Genre.ID" asp-items="@Model.Genres" class="form-control">
<option value="">Select a Genre/Genres</option>
</select>
<span asp-validation-for="Game.Genre" class="text-danger"></span>
</div>
Game / Create Controller :
[HttpGet]
public IActionResult Create()
{
GameCreateViewModel viewModel = new GameCreateViewModel();
viewModel.Game = new Game();
viewModel.Genres = genreService.GetAll().Select(x => new SelectListItem()
{
Text = x.Name,
Value = x.ID.ToString()
}).ToList();
viewModel.Developers = developerService.GetAll().Select(x => new SelectListItem()
{
Text = x.Name,
Value = x.ID.ToString()
}).ToList();
viewModel.Publishers = publisherService.GetAll().Select(x => new SelectListItem()
{
Text = x.Name,
Value = x.ID.ToString()
}).ToList();
viewModel.Platforms = platformService.GetAll().Select(x => new SelectListItem()
{
Text = x.Name,
Value = x.ID.ToString()
}).ToList();
return View(viewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(GameCreateViewModel viewModel)
{
Game game = new Game
{
ID = viewModel.Game.ID,
Name = viewModel.Game.Name,
Genre = viewModel.Game.Genre,
Developer = viewModel.Game.Developer,
Publisher = viewModel.Game.Publisher,
Description = viewModel.Game.Description,
Platform = viewModel.Game.Platform
};
gameService.Insert(game);
return RedirectToAction("Index");
}
Похоже, он также пытается вставить новую запись для внешних ключей, хотя я просто хочу использовать существующие идентификаторы для новой записи Game
. Например, новый Game
имеет GenreID 1, поэтому он должен относиться к существующей записи Genre с идентификатором 1.
Любое понимание этого очень ценится. Кроме того, дайте мне знать, если вам также нужны методы службы и репо. Спасибо за ваше время.