Je divise les données de test en deux modèles, Author
et Post
. L'amorçage fonctionne pour Author
, mais semble échouer silencieusement pour Post
.
Modifier: je pense avoir trouvé la source du problème. J'ai attrapé l'exception, et le message est
Impossible d'insérer une valeur explicite pour la colonne d'identité dans la table
Post
lorsqueIDENTITY_INSERT
est défini sur OFF.
Il peut y avoir une solution de contournement pour cela dans ce post StackOverflow , mais je me demandais si quelqu'un avait une idée de pourquoi cela se produit? Est-ce parce que nous ne devrions pas définir manuellement la valeur de la clé primaire?
Je perds la suite ce didacticiel Microsoft Docs , mais en utilisant ASP.NET MVC Core 2.1. La stratégie de base est que la méthode Main ()
de la classe Program
appelle DbInitializer.Initialize ()
, qui amorce les données s'il n'y en a pas Auteurs
dans le contexte.
J'ai dépassé la classe DbInitializer
, et le code passe par le même processus pour les deux modèles, en boucle sur le tableau, en l'ajoutant au contexte et (apparemment) en enregistrant les modifications. Cependant, alors que les champs de la base de données Author
sont remplis avec des données de départ, les champs Post
ne le sont pas.
Modifier: en parcourant et en inspectant le contexte généré, parfois les champs Auteur
ont d'étranges valeurs ID
et parfois le code Post > les champs ont d'étranges valeurs
ID
: -2147492647, -2147492646, etc ... J'ai essayé de changer PostID
en ID
par hasard que cela a causé le problème, mais le même problème se produit avec ce nom de champ.
Ma seconde réflexion est de me demander si cela a quelque chose à voir avec la relation plusieurs-à-un entre le message et l'auteur. Cependant, j'ai essayé de semer les données Post
avec uniquement le champ Title
(donc en excluant la clé étrangère AuthorID
), et cela n'a pas fait une différence. Je suis nouveau sur ASP.NET donc mon espoir est qu'il me manque quelque chose d'évident. Merci pour n'importe quelle direction.
MyWebsiteContext.cs
namespace MyWebsite.Models { public class Author { public int ID { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public DateTime SignUpDate { get; set; } } }
DbInitializer.cs p >
namespace MyWebsite.Models { public class Post // Post entity is dependent on Author class { public int PostID { get; set; } // primary key public string Title { get; set; } public int AuthorID { get; set; } // foreign key public Author Author { get; set; } } }
Program.cs
using System; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using MyWebsite.Data; using MyWebsite.Models; namespace MyWebsite { public class Program { public static void Main(string[] args) { var host = CreateWebHostBuilder(args).Build(); using (var scope = host.Services.CreateScope()) { var services = scope.ServiceProvider; try { var context = services.GetRequiredService<MyWebsiteContext>(); DbInitializer.Initialize(context); } catch(Exception ex) { var logger = services.GetRequiredService<ILogger<Program>>(); logger.LogError(ex, "An error occurred creating the DB."); } } host.Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>(); } }
Post.cs p >
using MyWebsite.Models; namespace MyWebsite.Data { public class DbInitializer { public static void Initialize(MyWebsiteContext context) { // Look for any authors; if none, seed DB. if (context.Author.Any()) { return; // DB has already been seeded. } var authors = new Author[] { new Author{ FirstName="Terry",LastName="Pratchett",SignUpDate=DateTime.Parse("2019-04-01")}, new Author{ FirstName="Neil",LastName="Gaiman",SignUpDate=DateTime.Parse("2019-03-02")}, }; foreach (Author a in authors) { context.Author.Add(a); } context.SaveChanges(); var posts = new Post[] { new Post{PostID=1,Title="Title of post 1"}, new Post{PostID=2,Title="Title of post 2"}, new Post{PostID=3,Title="Title of post 3"}, }; foreach (Post p in posts) { context.Post.Add(p); } context.SaveChanges(); } } }
Author.cs
using Microsoft.EntityFrameworkCore; using MyWebsite.Models; namespace MyWebsite.Models { public class MyWebsiteContext : DbContext { public MyWebsiteContext (DbContextOptions<MyWebsiteContext> options) : base(options) { } public DbSet<MyWebsite.Models.Author> Author { get; set; } public DbSet<MyWebsite.Models.Post> Post { get; set; } } }
3 Réponses :
Essayez ceci pour voir si cela fonctionne. J'ai ce même problème depuis que je travaille avec l'entité relationnelle de semis. Ma recommandation est d'essayer de mettre try catch dans votre code pour voir s'il y a une exception
Dans votre Program.cs
public static async Task Initialize(IServiceProvider serviceProvider) { using (var context = new ApplicationDbContext( serviceProvider.GetRequiredService<DbContextOptions<ApplicationDbContext>>())) { if (!context.Posts.Any()) { post.Comments = comments; await SeedPost(context); } } }
Puis graine comme ceci
XXX
Vous pouvez voir que mon entité Post a une liste de commentaires, donc je vais également attribuer une liste de commentaires dans l'objet Post puis semer en une fois
Vous pouvez voir mon code complet ici
Hé, merci beaucoup. Je ne savais pas qu'une exception était générée. (Il était capturé avec mon code d'origine mais je n'ai pas remarqué que cela se produisait.) Cela m'a conduit à la réponse. Très appréciée.
La première fois qu'il exécute l'opération SaveChange () avec succès, mais la deuxième fois, il faut une erreur pour ajouter des articles en raison de l'absence de clé étrangère de l'auteur, et l'opération n'est pas effectuée. Utilisez toujours un SaveChange!
Vous devez ajouter la clé étrangère AuthorId au modèle de publication ou mapper l'objet Author à l'objet Post.Author pour créer une relation
public static void Initialize(MyWebsiteContext context) { // Look for any authors; if none, seed DB. if (context.Author.Any()) { return; // DB has already been seeded. } var authors = new Author[] { new Author{ FirstName="Terry",LastName="Pratchett",SignUpDate=DateTime.Parse("2019-04-01")}, new Author{ FirstName="Neil",LastName="Gaiman",SignUpDate=DateTime.Parse("2019-03-02")}, }; foreach (Author a in authors) { context.Author.Add(a); } var posts = new Post[] { new Post{PostID=1,Title="Title of post 1" ,Author = authors[0] }, new Post{PostID=2,Title="Title of post 2" ,Author = authors[0]}, new Post{PostID=3,Title="Title of post 3" ,Author = authors[0]}, }; foreach (Post p in posts) { context.Post.Add(p); } context.SaveChanges(); }
Merci pour le commentaire et pour m'avoir montré comment associer Author
à Post.Author
! Il semble que j'ai dû a) mapper Author
à Post.Author
, et b) supprimer l'affectation PostID
.
Deux choses devaient être corrigées dans le code d'origine:
La définition de PostID
lors de l'amorçage. Les deux options sont soit a) supprimer cette définition, soit b) activer explicitement IDENTITY_INSERT
dans SQL Server. La deuxième méthode est décrite ici , mais pour mon fins, simplement supprimer la définition a fonctionné.
Mappage de l'objet Author
vers Post.Author
. Il ne suffisait pas d'appeler simplement new Post {Title = "Title of post 1"}
; la spécification de l ' Auteur
était obligatoire.
Segment DbInitializer
pertinent:
var posts = new Post[] { new Post{Title = "Title of post 1", Author = authors[0]}, new Post{Title = "Title of post 2", Author = authors[0]}, new Post{Title = "Title of post 3", Author = authors[1]}, };
Merci pour toute l'aide.