Skip to content

Commit d203fac

Browse files
committed
Add EF Core 3.1 database seeding example.
1 parent f4ad15a commit d203fac

5 files changed

Lines changed: 267 additions & 0 deletions

File tree

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"version": 1,
3+
"isRoot": true,
4+
"tools": {
5+
"dotnet-ef": {
6+
"version": "3.1.7",
7+
"commands": [
8+
"dotnet-ef"
9+
]
10+
}
11+
}
12+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>netcoreapp3.1</TargetFramework>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<PackageReference Include="Bogus" Version="30.0.4" />
10+
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.7">
11+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
12+
<PrivateAssets>all</PrivateAssets>
13+
</PackageReference>
14+
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.7" />
15+
</ItemGroup>
16+
17+
</Project>

Examples/EFCoreSeedDb/Program.cs

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using Bogus;
5+
using Bogus.Extensions;
6+
using Microsoft.EntityFrameworkCore;
7+
using static System.Console;
8+
9+
namespace EFCoreSeedDb
10+
{
11+
class Program
12+
{
13+
static void Main(string[] args)
14+
{
15+
WriteLine("Bogus Blog Example!");
16+
17+
using var ctx = new BloggingContext();
18+
19+
var blogs = ctx.Blogs
20+
.Include(b => b.Posts)
21+
.ToList();
22+
23+
foreach( var blog in blogs)
24+
{
25+
WriteLine($"Blog Id: {blog.BlogId}");
26+
WriteLine($"Blog Url: {blog.Url}");
27+
foreach( var post in blog.Posts )
28+
{
29+
WriteLine($" Post Id: {post.PostId}");
30+
WriteLine($" Title: {post.Title}");
31+
WriteLine($" Content: {post.Content}");
32+
}
33+
34+
WriteLine();
35+
WriteLine();
36+
}
37+
}
38+
39+
}
40+
41+
public class BloggingContext : DbContext
42+
{
43+
public DbSet<Blog> Blogs { get; set; }
44+
public DbSet<Post> Posts { get; set; }
45+
46+
protected override void OnConfiguring(DbContextOptionsBuilder options)
47+
{
48+
options.UseSqlite("Data Source=blogging.db");
49+
options.EnableSensitiveDataLogging();
50+
}
51+
52+
protected override void OnModelCreating(ModelBuilder modelBuilder)
53+
{
54+
base.OnModelCreating(modelBuilder);
55+
56+
FakeData.Init(10);
57+
58+
modelBuilder.Entity<Blog>().HasData(FakeData.Blogs);
59+
modelBuilder.Entity<Post>().HasData(FakeData.Posts);
60+
}
61+
62+
}
63+
64+
/// <summary>
65+
/// Example uses Faker[T]
66+
/// </summary>
67+
public static class FakeData
68+
{
69+
public static Faker<Blog> BlogFaker;
70+
public static Faker<Post> PostFaker;
71+
72+
public static List<Blog> Blogs = new List<Blog>();
73+
public static List<Post> Posts = new List<Post>();
74+
75+
public static void Init(int count)
76+
{
77+
var postId = 1;
78+
PostFaker = new Faker<Post>()
79+
.RuleFor(p => p.PostId, _ => postId++)
80+
.RuleFor(p => p.Title, f => f.Hacker.Phrase())
81+
.RuleFor(p => p.Content, f => f.Lorem.Sentence());
82+
83+
var blogId = 1;
84+
BlogFaker = new Faker<Blog>()
85+
.RuleFor(b => b.BlogId, _ => blogId++)
86+
.RuleFor(b => b.Url, f => f.Internet.Url())
87+
.RuleFor(b => b.Posts, (f, b) =>
88+
{
89+
var posts = PostFaker.GenerateBetween(3, 5);
90+
FakeData.Posts.AddRange(posts);
91+
92+
foreach( var post in posts )
93+
{
94+
post.BlogId = b.BlogId;
95+
}
96+
97+
return null; // Blog.Posts is a getter only. The return value has no impact.
98+
});
99+
100+
Blogs = BlogFaker.Generate(count);
101+
}
102+
}
103+
104+
/// <summary>
105+
/// Example uses Faker facade
106+
/// </summary>
107+
public static class FakeData2
108+
{
109+
public static int BlogId = 1;
110+
public static List<Blog> Blogs = new List<Blog>();
111+
112+
public static int PostId = 1;
113+
public static List<Post> Posts = new List<Post>();
114+
115+
private static Faker f;
116+
117+
public static void Init(int count)
118+
{
119+
f = new Faker();
120+
121+
GenerateBlogs(count);
122+
}
123+
124+
private static void GenerateBlogs(int blogCount)
125+
{
126+
for( var i = 0; i < blogCount; i++, BlogId++ )
127+
{
128+
var blog = new Blog
129+
{
130+
BlogId = BlogId,
131+
Url = f.Internet.Url()
132+
};
133+
134+
Blogs.Add(blog);
135+
136+
var postCount = f.Random.Number(3, 5);
137+
GeneratePost(blog, postCount);
138+
};
139+
}
140+
141+
private static void GeneratePost(Blog b, int postCount)
142+
{
143+
for( var i = 0; i < postCount; i++, PostId++ )
144+
{
145+
var post = new Post
146+
{
147+
PostId = PostId,
148+
BlogId = b.BlogId,
149+
Title = f.Hacker.Phrase(),
150+
Content = f.Lorem.Sentence()
151+
};
152+
153+
Posts.Add(post);
154+
}
155+
}
156+
}
157+
158+
public class Blog
159+
{
160+
public int BlogId { get; set; }
161+
public string Url { get; set; }
162+
163+
public List<Post> Posts { get; } = new List<Post>();
164+
}
165+
166+
public class Post
167+
{
168+
public int PostId { get; set; }
169+
public string Title { get; set; }
170+
public string Content { get; set; }
171+
172+
public int BlogId { get; set; }
173+
public Blog Blog { get; set; }
174+
}
175+
}

Examples/EFCoreSeedDb/README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
[1]:https://docs.microsoft.com/en-us/ef/core/get-started/
2+
[2]:https://docs.microsoft.com/en-us/ef/core/modeling/data-seeding
3+
4+
## EF Core Seed Database Example with Bogus
5+
6+
#### Requirements
7+
* **.NET Core 3.1** or later
8+
* **EF Core 3.1** or later
9+
10+
#### Description
11+
12+
The `EFCoreSeedDb` example is based on the [**EF Core Tutorial**][1] with the [**HasData**][2] method using **Bogus**.
13+
14+
To run the example, perform the following commands *inside* this `EfCoreSeedDb` folder:
15+
16+
* `dotnet restore`
17+
* `dotnet build`
18+
* `dotnet ef migrations add InitialCreate`
19+
* `dotnet ef database update`
20+
* `dotnet run`
21+
22+
After the `dotnet` commands are executed above, you should have a `blogging.db` SQLite DB file that you can open and inspect the sample data generated from Bogus. Additionally, the `dotnet run` command will print out the data generated by Bogus to the console read from the `blogging.db` SQLite DB file.
23+
24+
The basic approach is to pre-generate your Bogus data in-memory, in static properties, before sending sample data to EF Core.
25+
26+
* `FakeData` - Uses the `Faker<T>` approach.
27+
* `FakeData2` - Uses the `Faker` facade approach.
28+
29+
Either approach above can be used; pick whichever fits your preference and coding style.

Examples/Examples.sln

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.29613.14
5+
MinimumVisualStudioVersion = 16.0.29613.14
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EFCoreSeedDb", "EFCoreSeedDb\EFCoreSeedDb.csproj", "{7B012C90-4B93-4DB8-A0BA-AA91460DE392}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Debug|x64 = Debug|x64
12+
Debug|x86 = Debug|x86
13+
Release|Any CPU = Release|Any CPU
14+
Release|x64 = Release|x64
15+
Release|x86 = Release|x86
16+
EndGlobalSection
17+
GlobalSection(SolutionProperties) = preSolution
18+
HideSolutionNode = FALSE
19+
EndGlobalSection
20+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
21+
{7B012C90-4B93-4DB8-A0BA-AA91460DE392}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
22+
{7B012C90-4B93-4DB8-A0BA-AA91460DE392}.Debug|Any CPU.Build.0 = Debug|Any CPU
23+
{7B012C90-4B93-4DB8-A0BA-AA91460DE392}.Debug|x64.ActiveCfg = Debug|Any CPU
24+
{7B012C90-4B93-4DB8-A0BA-AA91460DE392}.Debug|x64.Build.0 = Debug|Any CPU
25+
{7B012C90-4B93-4DB8-A0BA-AA91460DE392}.Debug|x86.ActiveCfg = Debug|Any CPU
26+
{7B012C90-4B93-4DB8-A0BA-AA91460DE392}.Debug|x86.Build.0 = Debug|Any CPU
27+
{7B012C90-4B93-4DB8-A0BA-AA91460DE392}.Release|Any CPU.ActiveCfg = Release|Any CPU
28+
{7B012C90-4B93-4DB8-A0BA-AA91460DE392}.Release|Any CPU.Build.0 = Release|Any CPU
29+
{7B012C90-4B93-4DB8-A0BA-AA91460DE392}.Release|x64.ActiveCfg = Release|Any CPU
30+
{7B012C90-4B93-4DB8-A0BA-AA91460DE392}.Release|x64.Build.0 = Release|Any CPU
31+
{7B012C90-4B93-4DB8-A0BA-AA91460DE392}.Release|x86.ActiveCfg = Release|Any CPU
32+
{7B012C90-4B93-4DB8-A0BA-AA91460DE392}.Release|x86.Build.0 = Release|Any CPU
33+
EndGlobalSection
34+
EndGlobal

0 commit comments

Comments
 (0)