Reputation: 615
I know how to seed data to a database with old .NET 5.0 in startup.cs
file using my Seeder
class with a Seed()
method creating some initial data.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, Seeder seeder)
{
seeder.Seed();
..............
// other configurations
}
How do I do this in .NET 6.0? There is no place to add my Seeder
class as an argument.
Upvotes: 31
Views: 56609
Reputation: 148
I know the question about .NET 6.0 but I think it's in the same concepts.
In my case, I'm using .NET 8.0, and using Microsoft.AspNetCore.Identity so I need to initialize the application with default values (Defulat User and Defulat Roles) in the database using seed methods.
So First I create a class and inside it, I define an enum "Contains the roles I have" and write the main info related to the default user "Name, Email, Password, Role...etc".
Then I create a class called ApplicationDbContextSeed
:
public class ApplicationDbContextSeed
{
public async Task<bool> SeedEssentialsAsync(UserManager<ApplicationUser> userManager,
RoleManager<IdentityRole> roleManager)
{
//Seed Roles
await roleManager.CreateAsync(new IdentityRole(Authorization.Roles.SuperUser.ToString()));
await roleManager.CreateAsync(new IdentityRole(Authorization.Roles.User.ToString()));
//Seed Default User
var defaultUser = new ApplicationUser
{
Firstname= Authorization.default_Firstname,
Lastrname= Authorization.default_Lastname,
UserName = Authorization.default_username,
Email = Authorization.default_email,
EmailConfirmed = true,
PhoneNumberConfirmed = true,
IsPasswordChanged = true,
IsActive = true
};
if (userManager.Users.All(u => u.Id != defaultUser.Id))
{
await userManager.CreateAsync(defaultUser, Authorization.default_password);
await userManager.AddToRoleAsync(defaultUser, Authorization.superuser_role.ToString());
}
return true;
}
}
In Program.cs :
var app = builder.Build();
if (args.Length == 1 && args[0].ToLower() == "seeddata")
await SeedData(app);
async Task SeedData(IHost app)
{
var scopedFactory = app.Services.GetService<IServiceScopeFactory>();
using (var scope = scopedFactory?.CreateScope())
{
var service = scope?.ServiceProvider.GetService<ApplicationDbContextSeed>();
var userManager = scope?.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
var roleManager = scope?.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
await service.SeedEssentialsAsync(userManager, roleManager);
}
}
After I created my first migration Add-Migration InitialCreate
and created the database using the statement Update-database
, the tables were empty, and I filled it with the initial data using the statement dotnet run seeddata
Hope it helps anybody stuck in this part.
Upvotes: 0
Reputation: 61
Seeder.cs
public static class Seeder
{
public static void Initialize(DatabaseContext context)
{
context.Database.EnsureCreated();
//your seeding data here
context.SaveChanges();
}
}
Program.cs
var app = builder.Build();
SeedDatabase();
void SeedDatabase()
using(var scope = app.Services.CreateScope())
try{
var scopedContext = scope.ServiceProvider.GetRequiredService<DatabaseContext>();
Seeder.Initialize(scopedContext);
}
catch{
throw;
}
as simple as it gets before using DI.
Upvotes: 5
Reputation: 1004
Use these links for detailed version:
Program.cs
var builder = WebApplication.CreateBuilder(args);
//Add services to the container.
builder.Services.AddDbContext<YourDbContext>(
optionsBuilder => optionsBuilder.UseSqlServer("Your connection string goes here") //install - Microsoft.EntityFrameworkCore.SqlServer to use ".UseSqlServer" extension method
builder.Services.AddScoped<DbInitializer>();
var app = builder.Build();
//Configure the HTTP-request pipeline
if (app.Environment.IsDevelopment())
{
app.UseItToSeedSqlServer(); //custom extension method to seed the DB
//configure other services
}
app.Run();
DbInitializerExtension.cs
internal static class DbInitializerExtension
{
public static IApplicationBuilder UseItToSeedSqlServer(this IApplicationBuilder app)
{
ArgumentNullException.ThrowIfNull(app, nameof(app));
using var scope = app.ApplicationServices.CreateScope();
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<YourDbContext>();
DbInitializer.Initialize(context);
}
catch (Exception ex)
{
}
return app;
}
}
DbInitializer.cs
internal class DbInitializer
{
internal static void Initialize(YourDbContext dbContext)
{
ArgumentNullException.ThrowIfNull(dbContext, nameof(dbContext));
dbContext.Database.EnsureCreated();
if (dbContext.Users.Any()) return;
var users = new User[]
{
new User{ Id = 1, Name = "Bruce Wayne" }
//add other users
};
foreach(var user in users)
dbContext.Users.Add(user);
dbContext.SaveChanges();
}
}
Upvotes: 18
Reputation: 126
In my case, I'm using Microsoft.AspNetCore.Identity and needed initialize application with default values in database using seed methods.
builder.Services.AddScoped<UserManager<ApplicationUser>>();
builder.Services.AddScoped<RoleManager<IdentityRole>>();
And after line containing
var app = builder.Build();
I have called the seeds methods:
using (var scope = app.Services.CreateScope())
{
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<Usuario>>();
var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
await DefaultRoles.SeedAsync(roleManager);
await DefaultAdmin.SeedAsync(userManager);
}
Upvotes: 5
Reputation: 234
I solved a similar problem as follows:
Program.cs (.NET 6)
...
builder.Services.AddScoped<IDbInitializer, DbInitializer>(); //can be placed among other "AddScoped" - above: var app = builder.Build();
...
SeedDatabase(); //can be placed above app.UseStaticFiles();
...
void SeedDatabase() //can be placed at the very bottom under app.Run()
{
using (var scope = app.Services.CreateScope())
{
var dbInitializer = scope.ServiceProvider.GetRequiredService<IDbInitializer>();
dbInitializer.Initialize();
}
}
Upvotes: 21
Reputation: 3025
I have never use your solution before. This is what I'm doing,
public class DataContext: DbContext
{
public DataContext(DbContextOptions options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
new DbInitializer(modelBuilder).Seed();
}
// Db sets
}
And
public class DbInitializer
{
private readonly ModelBuilder modelBuilder;
public DbInitializer(ModelBuilder modelBuilder)
{
this.modelBuilder = modelBuilder;
}
public void Seed()
{
modelBuilder.Entity<User>().HasData(
new User(){ Id = 1.... },
new User(){ Id = 2.... },
);
}
}
Then run the command
dotnet ef migrations add .......
To create migration file
And
dotnet ef database update
To update db
Upvotes: 23