c# - 数据库播种仅适用于一个模型,不适用于第二个模型

标签 c# asp.net-core .net-core asp.net-core-mvc entity-framework-core

我将测试数据植入两个模型:AuthorPost。播种对 Author 有效,但对于 Post 似乎默默失败。

编辑:我想我已经找到了问题的根源。我已经捕获了异常,消息是

Cannot insert explicit value for identity column in table Post when IDENTITY_INSERT is set to OFF.

this StackOverflow post 中可能有解决方法,但我想知道是否有人知道为什么会发生这种情况?这是因为我们不应该手动设置主键的值吗?

我正在失去关注this Microsoft Docs tutorial ,但使用 ASP.NET MVC Core 2.1。基本策略是,Program 类中的 Main() 方法调用 DbInitializer.Initialize(),如果没有数据,则该方法会播种数据。上下文中的作者

我已经跳过了DbInitializer类,并且代码对两个模型都经历了相同的过程,循环遍历种子数组,将其添加到上下文中并(显然)保存更改。但是,虽然 Author 数据库字段填充了种子数据,但 Post 字段却没有。

编辑:在单步执行和检查生成的上下文时,有时 Author 字段具有奇怪的 ID 值,有时 Post 字段具有奇怪的值ID 值:-2147492647、-2147492646 等...我尝试将 PostID 更改为 ID,以防万一这会导致问题,但该字段名称也会出现同样的问题。

我的第二个想法是想知道这是否与帖子和作者之间的多对一关系有关。但是,我尝试仅使用 Title 字段(因此排除外键 AuthorID)来种子 Post 数据,但这并没有有所作为。我是 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; }
    }
}

作者.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; }
    }
}

最佳答案

尝试一下看看是否有效。自从我使用播种关系实体以来,我遇到了同样的问题。我的建议是尝试在代码中放入 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 对象中,然后播种一次

您可以查看我的完整代码 here

关于c# - 数据库播种仅适用于一个模型,不适用于第二个模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56913741/

相关文章:

c# - 如何检测在 Roslyn 中委托(delegate)转换的隐式方法?

c# - 如何在 C# 中将数字转换为 dd/mm/yyyy 格式?

来自路径/路由的 ASP.NET Core API 搜索参数

c# - 为什么扩展方法只允许在非嵌套、非泛型静态类中使用?

c# - 我们可以将 xml 文档返回到客户端应用程序,而不是将其保存在特定目的地吗

c# - 如何在.NET Core中正确设置WEB API的策略授权

c# - 测试自定义工厂中间件

.net-core - 显示一对多数据模型的 ICollection 时 foreach 循环出错

c# - 编码指向数组 P/Invoke 的指针

css - 删除 css 包中的注释而不缩小文件