EF 2.1 中的种子数据与相关实体
Seed data in EF 2.1 with related entities
使用 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" }
);
但是,对于播种 posts,我从 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 文件是由第三方创建的,我无法更改它们。
要播种这些 post,我认为我需要:
- 为每个CategoryName获取对应的Category Id;
- 为每个post生成一个ID。
步骤 (2) 看起来很简单,但我怎样才能完成步骤 (1)?
To seed these posts I believe I need to:
Get the correspondent Category Id for each CategoryName;
Generate an ID for each post.
是的!你是对的!您必须在 Post
中使用 CategoryId
而不是 CategoryName
,因为 CategoryId
是关系键,而不是 CategoryName
。所以你的 YML 内容应该是这样的:
new {Id = 1, CategoryId = 1, Title = "A", Content = "A Content" },
new {Id = 2, CategoryId = 2, Title = "B", Content = "B Content" }
然后在DbConext
的OnModelCreating
如下:
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);
}
These YML files are created by a third party and I cannot change them.
然后你必须编写一个自定义服务方法,你将使用 CategoryName
检查 YMl 文件中的每个 post 然后你必须制作新的 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;
}
}
然后在DbConext
的OnModelCreating
如下:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
var categories = SeedDataService.GetCategoriesForSeeding();
modelBuilder.Entity<Category>().HasData(categories);
var posts = SeedDataService.GetPostsForSeeding();
modelBuilder.Entity<Post>().HasData(posts);
}
不要将类别播种到位,而是先将它们保存到变量中:
var categories = new[]
{
new Category { Id = 1, Name = "Reading" },
new Category { Id = 2, Name = "Traveling" }
};
然后,将其传递给 HasData
:
modelBuilder.Entity<Category>().HasData(categories);
现在,您可以在内存中查询此列表以获取相关类别,同时将 YML 数据映射到 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
});
CategoryId
是不可为空的,因此如果 YML 中命名的特定类别实际上不存在,您可能想要创建一个回退。您甚至可以考虑从 post YML 中自己播种类别,以确保其中的所有内容确实存在:
var categories = posts.Select(p => p.CategoryName).Distinct().Select((c, i) => new Category
{
Id = i,
Name = c
}).ToArray();
使用 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" }
);
但是,对于播种 posts,我从 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 文件是由第三方创建的,我无法更改它们。
要播种这些 post,我认为我需要:
- 为每个CategoryName获取对应的Category Id;
- 为每个post生成一个ID。
步骤 (2) 看起来很简单,但我怎样才能完成步骤 (1)?
To seed these posts I believe I need to:
Get the correspondent Category Id for each CategoryName;
Generate an ID for each post.
是的!你是对的!您必须在 Post
中使用 CategoryId
而不是 CategoryName
,因为 CategoryId
是关系键,而不是 CategoryName
。所以你的 YML 内容应该是这样的:
new {Id = 1, CategoryId = 1, Title = "A", Content = "A Content" },
new {Id = 2, CategoryId = 2, Title = "B", Content = "B Content" }
然后在DbConext
的OnModelCreating
如下:
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);
}
These YML files are created by a third party and I cannot change them.
然后你必须编写一个自定义服务方法,你将使用 CategoryName
检查 YMl 文件中的每个 post 然后你必须制作新的 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;
}
}
然后在DbConext
的OnModelCreating
如下:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
var categories = SeedDataService.GetCategoriesForSeeding();
modelBuilder.Entity<Category>().HasData(categories);
var posts = SeedDataService.GetPostsForSeeding();
modelBuilder.Entity<Post>().HasData(posts);
}
不要将类别播种到位,而是先将它们保存到变量中:
var categories = new[]
{
new Category { Id = 1, Name = "Reading" },
new Category { Id = 2, Name = "Traveling" }
};
然后,将其传递给 HasData
:
modelBuilder.Entity<Category>().HasData(categories);
现在,您可以在内存中查询此列表以获取相关类别,同时将 YML 数据映射到 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
});
CategoryId
是不可为空的,因此如果 YML 中命名的特定类别实际上不存在,您可能想要创建一个回退。您甚至可以考虑从 post YML 中自己播种类别,以确保其中的所有内容确实存在:
var categories = posts.Select(p => p.CategoryName).Distinct().Select((c, i) => new Category
{
Id = i,
Name = c
}).ToArray();