Search code examples
c#entity-frameworkweb-applicationsasp.net-core-2.2

ASP. NET Core 2.2 EF - Database Not Seeding


I am in the process of developing a MVC web application using Asp .Net Core 2.2 and EntityFramework. I'm quite new to the framework and I'm trying to seed the database but on testing, the database is still empty. I have looked at previous posts about calling my Initialize method through Program.cs which I have attempted to implement so I'm unsure what I've missed? I've tried to find an answer what may be going on but other solutions point to previous versions of the framework.

Any help would be greatly appreciated!

My database initialize method is as follows:

public static void Initialize(ApplicationDbContext context)
    {
        {
            //Look for any IncidentTypes
            if (context.IncidentType.Any())
            {
                return; // DB has been seeded
            }

            var incidentTypes = new IncidentType[]
            {
                 new IncidentType { Id = 1, Type = "Urgent"},
                 new IncidentType { Id = 2,Type = "Non-Urgent"}
            };

            foreach (IncidentType t in incidentTypes)
            {
                context.IncidentType.Add(t);
            }
            context.SaveChanges();

            var outcomes = new Outcome[]
            {
                new Outcome { Id = 1, OutcomeText = "This type of incident does not apply"},
                new Outcome { Id = 2, OutcomeText = "Go to ED"},
                new Outcome { Id = 3, OutcomeText = "Go to ED"},
                new Outcome { Id = 4, OutcomeText = "CLEAR & LEAVE"}
            };

            foreach (Outcome o in outcomes)
            {
                context.Outcome.Add(o);
            }
            context.SaveChanges();

            var stages = new Stage[]
            {
                new Stage { Id = 1, OutcomeId = 1, StageName = "Complete PS"},
                new Stage { Id = 2, OutcomeId = 2, StageName = "Do Any Apply?"},
                new Stage { Id = 3, OutcomeId = 3, StageName = "Do Any Apply?"},
                new Stage { Id = 4, OutcomeId = 4, StageName = "Do Any Apply?"}
            };

            foreach (Stage s in stages)
            {
                context.Stage.Add(s);
            }
            context.SaveChanges();

            var stageConditions = new StageCondition[]
            {
                new StageCondition { Id = 1, IncidentTypeId = 1, StageId = 1,
                    ConditionText = "This process does not apply to the following: INSERT"},
                new StageCondition { Id = 2, IncidentTypeId = 1, StageId = 2,
                    ConditionText = "First set of Questions"},
                new StageCondition { Id = 3, IncidentTypeId = 1, StageId = 3,
                    ConditionText = "Second set of Questions"},
                new StageCondition { Id = 4, IncidentTypeId = 1, StageId = 4,
                    ConditionText = "Is there a suitable ED alternative?"},
                new StageCondition { Id = 5, IncidentTypeId = 2, StageId = 1,
                    ConditionText = "This process does not apply to the following: INSERT"},
                new StageCondition { Id = 6, IncidentTypeId = 2, StageId = 2,
                    ConditionText = "First set of Questions"},
                new StageCondition { Id = 7, IncidentTypeId = 2, StageId = 3,
                    ConditionText = "Second set of Questions"},
                new StageCondition { Id = 8, IncidentTypeId = 2, StageId = 4,
                    ConditionText = "Is there a suitable ED alternative?"}
            };

            foreach (StageCondition c in stageConditions)
            {
                context.StageCondition.Add(c);
            }
            context.SaveChanges();
        }

My Program.cs class is as follows:

public class Program
{
    public static void Main(string[] args)
    {
        var host = CreateWebHostBuilder(args).Build();

        using (var scope = host.Services.CreateScope())
        {
            var services = scope.ServiceProvider;

            try
            {
                var context = services.GetRequiredService<ApplicationDbContext>();
                DbInitializer.Initialize(context);
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occured creating the DB.");
            }
        }

        host.Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

and my database context is as follows:

public class ApplicationDbContext : IdentityDbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }
    public DbSet<Models.IncidentType> IncidentType { get; set; }
    public DbSet<Models.Incident> Incident { get; set; }
    public DbSet<Models.StageCondition> StageCondition { get; set; }
    public DbSet<Models.Outcome> Outcome { get; set; }
    public DbSet<Models.Stage> Stage { get; set; }
}

EDIT: Added IncidentType model below:

    public class IncidentType
{
    public int Id { get; set; }
    public string Type { get; set; }
}

}


Solution

  • Your project is failing due to IDENTITY_INSERT which is by default turned ON. Entity framework by convention treats Id /Id as Primary Keys and is unable to insert records with given "Id". Please rename this field if you don't want to treat it as Primary Key but I'd advise to leave it as it is and allow it to work.

    Additionally I'd recommend to read about Dependency Injection and injecting DatabaseSeeder as Singleton to create one instance once application is started. It is bad practice to insert any kind of logic in Program class.