我正在将测试数据植入两个模型Author
和Post
中。播种适用于Author
,但似乎无声地失败了Post
。
编辑:我想我已经找到了问题的根源。我发现了异常,消息是
Post
设置为OFF时,无法为表IDENTITY_INSERT
中的标识列插入显式值。
在this StackOverflow post中可能有解决此问题的方法,但是我想知道是否有人对此有何想法?这是因为我们不应该手动设置主键的值吗?
我没有遵循this Microsoft Docs tutorial,但是使用的是ASP.NET MVC Core 2.1。基本策略是Main()
类中的Program
方法调用DbInitializer.Initialize()
,如果上下文中没有Authors
,它将为数据提供种子。
我已经跨过DbInitializer
类,两个模型的代码都经过相同的过程,遍历种子数组,将其添加到上下文中并(显然)保存更改。但是,虽然Author
数据库字段填充有种子数据,但Post
字段却未填充。
编辑:在逐步检查生成的上下文时,有时Author
字段具有奇怪的ID
值,有时Post
字段具有奇怪的ID
值:-2147492647 ,-2147492646等...我试图将导致问题的机会从PostID
更改为ID
,但是该字段名称也发生了同样的问题。
我的第二个想法是想知道这是否与Post和Author之间的多对一关系有关。但是,我尝试仅使用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; }
}
}
答案 0 :(得分:1)
尝试此操作是否有效。自从我为关系实体播种以来,我遇到了同样的问题。我的建议是尝试在代码中放入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
答案 1 :(得分:1)
第一次成功执行SaveChange()操作,但是第二次由于缺少作者的外键而添加帖子时出错,因此不执行该操作。 始终使用一个SaveChange!
必须将外键AuthorId添加到Post Model或将Author Object映射到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();
}
答案 2 :(得分:0)
原始代码中需要修复的两件事:
播种期间PostID
的定义。这两个选项是a)删除该定义,或b)在SQL Server中显式打开IDENTITY_INSERT
。 here讨论了第二种方法,但是出于我的目的,只需删除定义即可。
将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]},
};
感谢所有帮助。