EF 2.1中与相关实体的种子数据

时间:2018-10-02 12:11:31

标签: asp.net-core entity-framework-core asp.net-core-2.1 entity-framework-core-2.1

使用ASP.NET Core 2.1和Entity Framework Core 2.1,我具有以下实体:

public class Category {
  public Int32 Id { get; set; }
  public String Name { get; set; }
}

public class Post {
  public Int32 Id { get; set; }
  public Int32 CategoryId { get; set; }
  public String Title { get; set; }
  public String Content { get; set; }
  public virtual Category Category { get; set; }
}

对于播种类别,我有以下内容:

modelBuilder.Entity<Category>().HasData(
  new { Id = 1, Name = "Reading" },
  new { Id = 2, Name = "Travelling" }
);

但是,对于种子发布,我从YML文件中获取数据:

var posts = _service.GetPostsFromYMLFiles(path);

modelBuilder.Entity<Post>().HasData(posts);

posts来自YML文件,其内容如下:

new { CategoryName = "Reading", Title = "A", Content = "A Content" },
new { CategoryName = "Travelling", Title = "B", Content = "B Content" }

这些YML文件是由第三方创建的,我无法更改它们。

要播种这些帖子,我相信我需要:

  1. 获取每个CategoryName的对应类别ID;
  2. 为每个帖子生成一个ID。

步骤(2)似乎很简单,但是如何完成步骤(1)?

2 个答案:

答案 0 :(得分:1)

  

我认为我需要播种这些帖子

     

获取每个CategoryName的对应类别ID;

     

为每个帖子生成一个ID。

是的!你是对的!您必须在CategoryId中使用CategoryName而不是Post,因为CategoryId是关系密钥,而不是CategoryName。因此,您的YML内容应如下所示:

new {Id = 1, CategoryId = 1, Title = "A", Content = "A Content" },
new {Id = 2, CategoryId = 2, Title = "B", Content = "B Content" }

然后在OnModelCreating的{​​{1}}中进行如下操作:

DbConext
  

这些YML文件是由第三方创建的,我无法更改它们。

然后,您必须编写一种自定义服务方法,在其中使用protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); var posts = _service.GetPostsFromYMLFiles(path); modelBuilder.Entity<Category>().HasData( new { Id = 1, Name = "Reading"}, new { Id = 2, Name = "Travelling" } ); modelBuilder.Entity<Post>().HasData(posts); } 检查YMl文件中的每个帖子,然后必须制作CategoryName的新列表,并在其中替换为Post CategoryName及其适当的值,如下所示:

CateogryId

然后在public class YmlPost { public string CategoryName { get; set; } public string Title { get; set; } public string Content { get; set; } } public class SeedDataService { static List<Category> categoryList = new List<Category>() { new Category { Id = 1, Name = "Reading" }, new Category { Id = 2, Name = "Traveling" } }; public static List<Category> GetCategoriesForSeeding() { return categoryList; } public static List<Post> GetPostsForSeeding() { List<YmlPost> postListFromYML = _service.GetPostsFromYMLFiles(path); List<Post> posts = postListFromYML.Select((p, i) => new Post { Id = i+1, // index is 0 based that's why you have to add 1. Title = p.Title, Content = p.Content, CategoryId = categoryList.Single(c => c.Name == p.CategoryName).Id }).ToList(); return posts; } } 的{​​{1}}中进行如下操作:

OnModelCreating

答案 1 :(得分:1)

代替将类别播种到位,而是先将它们保存到变量中:

onMessageReceived

然后,将其传递给var categories = new[] { new Category { Id = 1, Name = "Reading" }, new Category { Id = 2, Name = "Traveling" } };

HasData

有了它,您现在可以在将YML数据映射到modelBuilder.Entity<Category>().HasData(categories); 实体时查询内存中的此列表以获取相关类别:

Post

var posts = _service.GetPostsFromYMLFiles(path); modelBuilder.Entity<Post>().HasData(posts.Select((p, i) => new Post { Id = i, Title = p.Title, Content = p.Content, CategoryId = categories.Single(c => c.Name == p.CategoryName).Id }); 是不可为空的,因此,如果YML中命名的特定类别实际上不存在,则可能要创建一个后备。您甚至可以考虑从YML帖子中播种类别本身,以确保其中的所有内容确实存在:

CategoryId