I'm trying to seed my db with some data stored in json files.
I need to inject an IHostingEnvironment
inside my IDatabaseInitializer.Seed()
method so I can read the json files using IHostingEnvironment.ContentRootPath
.
This property is injected by the main container by default but the constructor of an DbConfiguration
must be parameterless, so I can't pipe IHostingEnvironment
through DbConfiguration
into SetDatabaseInitializer(new DatabaseInitializer())
.
/*
* Database Context
*/
[DbConfigurationType(typeof(DatabaseConfiguration))]
public class DatabaseContext : DbContext
{
public DbSet<User> Users { get; set; }
public DatabaseContext(string nameOrConnectionString) : base(nameOrConnectionString) { }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention>();
base.OnModelCreating(modelBuilder);
}
}
/*
* Database Configuration
*/
public class DatabaseConfiguration : DbConfiguration
{
// Can't receive injected IHostingEnvironment env because constructor must be parameterless
public DatabaseConfiguration()
{
SetProviderServices("System.Data.SqlClient", SqlProviderServices.Instance);
// Could pass IHostingEnvironment through constructor
SetDatabaseInitializer(new DatabaseInitializer());
}
}
/*
* Database Initializer
*/
public class DatabaseInitializer : DropCreateDatabaseAlways<DatabaseContext>
{
private readonly IHostingEnvironment env;
// Receives IHostingEnvironment from DatabaseConfiguration
public DatabaseInitializer(IHostingEnvironment env)
{
this.env = env;
}
protected override void Seed(DatabaseContext context)
{
// Read some .json files
}
}
I'm initializing my db, and had to write a separate class, which I call from configure, you could do the same thing and pass in the path as a parameter
Here's how I call it:
using (var scope = scopeFactory.CreateScope())
{
// Initialise Database
var initializer = scope.ServiceProvider.GetService<IDbInitializer>();
initializer.SeedAsync().Wait();
// initialize plugin manager
var manager = scope.ServiceProvider.GetService<IPluginManager>();
manager.Initialize(dbConnection);
if (Configuration.GetSection("PluginService").GetValue<bool>("RunAtStartup") == true)
manager.Start();
}
and here's the db initialize class
public interface IDbInitializer
{
Task SeedAsync();
}
public class DbInitializer : IDbInitializer
{
private ApplicationDbContext _context;
private RoleManager<IdentityRole> _roleManager;
private UserManager<ApplicationUser> _userManager;
public DbInitializer(ApplicationDbContext context,
RoleManager<IdentityRole> roleManager,
UserManager<ApplicationUser> userManager)
{
_context = context;
_roleManager = roleManager;
_userManager = userManager;
}
public async Task SeedAsync()
{
await CreateRolesAsync();
await CreateAdminUserAsync();
await SeedMenuAsync();
}
private async Task CreateRolesAsync()
{
List<IdentityRole> roles = new List<IdentityRole>();
roles.Add(new IdentityRole { Name = "Admin", NormalizedName = "ADMINISTRATOR" });
roles.Add(new IdentityRole { Name = "Member", NormalizedName = "MEMBER" }); // An email confirmed memeber
roles.Add(new IdentityRole { Name = "Guest", NormalizedName = "GUEST" }); // Used for a user that has only checked out as guest
roles.Add(new IdentityRole { Name = "NotConfirmed", NormalizedName = "NOTCONFIRMED" }); // Used when a guest hasnt confirmed there registration
foreach (var role in roles)
{
var roleExists = await _roleManager.RoleExistsAsync(role.Name);
if (!roleExists)
{
await _roleManager.CreateAsync(role);
}
}
}
...
Hope that helps