[Q] C# - EF relation
Så jag har en situation där jag har två modeller (klasser):
public class Game
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public int DeveloperId { get; set; }
public string Description { get; set; }
public int PublishedYear { get; set; }
public List<Rating> Ratings { get; set; }
public List<Genre> Genres { get; set; } // <------ denna som jag misslyckas med
}
public class Genre
{
[Key]
public int Id { get; set; }
public bool KidsFriendly { get; set; } = true;
public string Name { get; set; }
}
Jag exekverar en kod där jag har en collection av spel som har en collection i sig av Genre, ett exempel:
var games = new List<Game>() {
new Game()
{
Name = "<namn>",
Description = "<beskrivning>",
Genres = new List<Genre>(){ GenreController.GetOneGenreByName("<genre namn>"), GenreController.GetOneGenreByName("<genre namn>")},
PublishedYear = <år>,
Ratings = new List<Rating>(), //utebliven för nu, då jag inte lyckas få genre att fungera ens
DeveloperId = <utvecklare>.Id
}
}
db.Games.AddRange(games);
db.SaveChanges();
Jag får två problem, när jag kör AddRange får jag felmeddelandet att:
An unexpected error occured in the creation phase of games: The instance of entity type 'Genre' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values. ().
Om jag kör en gammal hederlig Add får jag:
An unexpected error occured in the creation phase of games: An error occurred while updating the entries. See the inner exception for details. (MySqlConnector.MySqlException (0x80004005): Duplicate entry '94' for key 'Genre.PRIMARY'
at MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior ioBehavior) in /_/src/MySqlConnector/Core/ResultSet.cs:line 50
at MySqlConnector.MySqlDataReader.ActivateResultSet(CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 137
at MySqlConnector.MySqlDataReader.CreateAsync(CommandListPosition commandListPosition, ICommandPayloadCreator payloadCreator, IDictionary`2 cachedProcedures, IMySqlCommand command, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 445
at MySqlConnector.Core.CommandExecutor.ExecuteReaderAsync(IReadOnlyList`1 commands, ICommandPayloadCreator payloadCreator, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/Core/CommandExecutor.cs:line 60
at MySqlConnector.MySqlCommand.ExecuteReaderAsync(CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlCommand.cs:line 314
at MySqlConnector.MySqlCommand.ExecuteDbDataReader(CommandBehavior behavior) in /_/src/MySqlConnector/MySqlCommand.cs:line 256
at System.Data.Common.DbCommand.ExecuteReader()
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection)).
Min avsedda relation är att:
Spel kan ha oändligt antal mot Genre
Genre ska kunna appliceras utan att skapas på nytt
Databasens tabeller över de två:
Games
CREATE TABLE `Games` (
`Id` int NOT NULL AUTO_INCREMENT,
`Name` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
`DeveloperId` int DEFAULT NULL,
`Description` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
`PublishedYear` int NOT NULL,
PRIMARY KEY (`Id`),
KEY `IX_Games_DeveloperId` (`DeveloperId`),
CONSTRAINT `FK_Games_Developer_DeveloperId` FOREIGN KEY (`DeveloperId`) REFERENCES `Developer` (`Id`) ON DELETE RESTRICT
) ENGINE=InnoDB AUTO_INCREMENT=120 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
EF
migrationBuilder.CreateTable(
name: "Games",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Name = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
DeveloperId = table.Column<int>(type: "int", nullable: false),
Description = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
PublishedYear = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Games", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
Genre
MySQL
CREATE TABLE `Genre` (
`Id` int NOT NULL AUTO_INCREMENT,
`KidsFriendly` tinyint(1) NOT NULL,
`Name` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
`GameId` int DEFAULT NULL,
PRIMARY KEY (`Id`),
KEY `IX_Genre_GameId` (`GameId`),
CONSTRAINT `FK_Genre_Games_GameId` FOREIGN KEY (`GameId`) REFERENCES `Games` (`Id`) ON DELETE RESTRICT
) ENGINE=InnoDB AUTO_INCREMENT=103 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
EF
migrationBuilder.CreateTable(
name: "Genre",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
KidsFriendly = table.Column<bool>(type: "tinyint(1)", nullable: false),
Name = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
GameId = table.Column<int>(type: "int", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Genre", x => x.Id);
table.ForeignKey(
name: "FK_Genre_Games_GameId",
column: x => x.GameId,
principalTable: "Games",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
})
.Annotation("MySql:CharSet", "utf8mb4");
TLDR;
Varför varje gång jag skapar ett Game-object mot databasen så försöker den skapa mina Genre-objekt samtidigt? Jag antar att en foreign key saknas eller att jag behöver sätta upp relationen i OnModelCreating?
Citera om du vill ha svar, hjälpte jag dig, gilla svaret!