Заполнение базы данных работает только для одной модели, а не для второй - PullRequest
1 голос
/ 06 июля 2019

Я загружаю данные теста в две модели, Author и Post.Заполнение работает для Author, но, похоже, не работает тихо для Post.

Редактировать: Я думаю, что нашел источник проблемы.Я поймал исключение, и сообщение

Невозможно вставить явное значение для столбца идентификаторов в таблице Post, если IDENTITY_INSERT установлено в OFF.

Для этого может быть обходной путь в этом посте StackOverflow , но мне было интересно, есть ли у кого-нибудь идеи, почему это происходит?Это потому, что мы не должны вручную устанавливать значение первичного ключа?

Я теряю после этого руководства по Microsoft Docs , но использую ASP.NET MVC Core 2.1.Основная стратегия заключается в том, что метод Main() в классе Program вызывает DbInitializer.Initialize(), который заполняет данные, если в контексте нет Authors.

Я перешагнул через DbInitializerкласс, и код проходит через один и тот же процесс для обеих моделей, циклически проходя через заполненный массив, добавляя его в контекст и (видимо) сохраняя изменения.Однако, хотя поля базы данных Author заполнены начальными данными, поля Post - нет.

Редактировать: при просмотре и проверке созданного контекста иногда поля Author имеют странные значения ID, а иногда поля Post имеют странные значения ID: -2147492647, -2147492646 и т. Д.... Я пытался изменить PostID на ID при вероятности того, что это вызвало проблему, но та же проблема возникает с этим именем поля.

Моя вторая мысль - интересно, есть ли в этом что-тоделать с отношениями многие-к-одному между почтой и автором.Однако я попытался заполнить данные Post только полем Title (исключая внешний ключ AuthorID), и это не имело значения.Я новичок в ASP.NET, поэтому я надеюсь, что мне не хватает чего-то очевидного.Спасибо за любое направление.

MyWebsiteContext.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; }
    }
}

DbInitializer.cs

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

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

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

Author.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; }
    }
}

Ответы [ 3 ]

1 голос
/ 06 июля 2019

Первый раз, когда он успешно выполняет операцию SaveChange (), но во второй раз он добавляет ошибку, чтобы добавить сообщения из-за отсутствия внешнего ключа автора, и операция не выполняется.Всегда используйте один SaveChange!

Вы должны добавить внешний ключ AuthorId для Post Model или сопоставить объект Author с объектом Post.Author для создания отношения

 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 голос
/ 06 июля 2019

Попробуйте, чтобы увидеть, работает ли это.У меня такая же проблема, так как я работаю с заполнением реляционной сущности.Я рекомендую попробовать добавить try catch в ваш код, чтобы увидеть, есть ли в нем какое-либо исключение

В вашем Program.cs

using (var scope = host.Services.CreateScope())
{
  var services = scope.ServiceProvider;
  SeedData.Initialize(services).Wait();
}

Затем заполняем так:

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

Вы можете видеть, что у моей сущности Post есть список комментариев, поэтому я также назначу список комментариев в объект Post, а затем за один раз зайду

Вы можете просмотреть мой полный код здесь

0 голосов
/ 07 июля 2019

В исходном коде необходимо исправить две вещи:

  1. Определение PostID при посеве. Два варианта: а) удалить это определение или б) явно включить IDENTITY_INSERT в SQL Server. Второй метод обсуждается здесь , но для моих целей просто удаление определения сработало.

  2. Отображение объекта Author на Post.Author. Простого вызова new Post{Title="Title of post 1"} было недостаточно; указав Author было необходимо.

Соответствующий DbInitializer сегмент:

            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]},
            };

Спасибо за помощь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...