My problem is i am trying to seed an Entity Framework Core database with data and in my mind the below code show work. I\'ve realised that this should not be called in the <
Assuming you are using the built-in DI container, here is one way you can accomplish this.
Reference your seed method in the Configure method of your startup class, and pass the IApplicationBuilder object as a parameter instead of the DbContext, like this:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
//...
// Put this at the end of your configure method
DbContextSeedData.Seed(app);
}
Next, modify your seed method to accept the IApplicationBuilder instance. Then you'll be able to spin up an instance of the DbContext, and perform your seed operation, like this:
public static void Seed(IApplicationBuilder app)
{
// Get an instance of the DbContext from the DI container
using (var context = app.ApplicationServices.GetRequiredService<ApplicationDbContext>())
{
// perform database delete
context.Database.EnsureDeleted;
//... perform other seed operations
}
}
You could also use from the Startup.cs ConfigureServices
method to make your ApplicationDbContext available (Registering the dbcontext as a service):
public void ConfigureServices(IServiceCollection services)
{
var connectionString = Startup.Configuration["connectionStrings:DBConnectionString"];//this line is not that relevant, the most important thing is registering the DbContext
services.AddDbContext<ApplicationDbContext>(o => o.UseSqlServer(connectionString));
}
and then add your ApplicationDbContext as dependency in your Configure
method which will call your seed extension method.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, ApplicationDbContext myApplicationDbContext)
{
//...
myApplicationDbContext.Seed();
}
Finally the seed method could do a quick check on an important table, because perhaps recreating the db is too heavy:
public void Seed()
{
//....
if(context.Countries.Any())
return;
//...
}
I hope it helps you or someone else, at least as another option.
If you want to run your EF code from a separate class library and do Seeding in that you can do the following. This is using TSQL...
1) Create a new class library. Add the following dependencies with NuGet...
Microsoft.AspNetCore
Microsoft.AspNetCore.Identity.EntityFrameworkCore
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools
2) Point the Package Manager Console at this project and run...
PM> add-migration Seeder01
then...
PM> update-database
this gives you an empty migration.
3) Script the updates as something like...
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Migrations;
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Configuration;
using System.IO;
namespace Test02.Data.Migrations
{
public partial class Seeder01 : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
string sql = string.Empty;
sql = "SET IDENTITY_INSERT State ON;";
sql += "Insert into State (Id, Name) values ";
sql += "(2, 'NSW'),";
sql += "(3, 'VIC'),";
sql += "(4, 'QLD'),";
sql += "(5, 'SA')";
sql += ";";
sql += "SET IDENTITY_INSERT State OFF;";
migrationBuilder.Sql(sql);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
string sql = string.Empty;
sql = "delete State;";
migrationBuilder.Sql(sql);
}
}
}
4) Revert to the prior migration with...
PM> add-migration {PriorMigrationName}
Reload the seed migration and update the database...
PM> add-migration Seeder01
PM> update-database