2
votes

L'amorçage de la base de données ne fonctionne que pour un modèle, pas un second

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 lorsque IDENTITY_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; }
    }
}


0 commentaires

3 Réponses :


1
votes

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


1 commentaires

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.



2
votes

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();
        }


1 commentaires

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 .



0
votes

Deux choses devaient être corrigées dans le code d'origine:

  1. 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é.

  2. 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.


0 commentaires