EF Core 9.0 (EF 9) introduced new methods UseSeeding and UseAsyncSeeding to seed the initial data.
Let's have a look at an example.
Consider the following MyDbContext.
public record Blog
{
public int Id { get; set; }
public string Name { get; set; }
}
public class MyDbContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseSqlServer("<ConnectionString>");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>(x =>
{
x.HasData
(
new Blog
{
Id = 1,
Name = "Some Blog"
}
);
});
}
}
Here in the above example, some data is seeded through Model-managed data
which is handly when we want to include seed data in migrations as well and it
was available for as far as I can remember.
Now let's see where UseSeeding and UseAsyncSeeding come in.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseSqlServer("<ConnectionString>")
.UseSeeding((context, _) =>
{
Blog? blog = context.Set<Blog>().SingleOrDefault(b => b.Name == "Some Other Blog");
if (blog is null)
{
context.Set<Blog>().Add(new Blog { Name = "Some Other Blog" });
context.SaveChanges();
}
})
.UseAsyncSeeding(async (context, _, cancellationToken) =>
{
Blog? blog = await context.Set<Blog>().SingleOrDefaultAsync(b => b.Name == "Some Other Blog", cancellationToken);
if (blog is null)
{
context.Set<Blog>().Add(new Blog { Name = "Some Other Blog" });
await context.SaveChangesAsync(cancellationToken);
}
});
}
As you can see, the new seeding methods are available as part of
configuring DbContextOptions. Unlike Model-managed data, you can seed data for multiple DbSets all from a
single place. These methods will get called as part of
EnsureCreated
operation,
Migrate
and
dotnet ef database update
command, even if there are no model changes and no migrations were applied.
Now let's see this in action.
using var context = new MyDbContext();
await context.Database.EnsureDeletedAsync();
await context.Database.EnsureCreatedAsync();
foreach (Blog blog in context.Blogs)
{
Console.WriteLine(blog.Name);
}
// Output:
//Some Blog
//Some Other Blog
And a note from the official documentation:
UseSeeding is called from the EnsureCreated method, and UseAsyncSeeding is called from the EnsureCreatedAsync method. When using this feature, it is recommended to implement
both UseSeeding and UseAsyncSeeding methods using similar logic, even if the code using EF is
asynchronous. EF Core tooling currently relies on the synchronous version of
the method and will not seed the database correctly if the UseSeeding method is not implemented.
More read:
EF Core: Data Seeding
Happy Coding.
Regards,
Jaliya