Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Seeding Data MVC 6 .NET Core Application

0.00/5 (No votes)
14 Aug 2019 1  
Seeding data in MVC 6 .NET Core 2.2 application at startup

Table of Contents

Goal

Just like MVC 5, I was trying to enable automatic migrations and Seeding default data, but it seems the behaviour has been changed in MVC 6, so I thought I'll share the tip.

Introduction

Here, we'll try to learn Seeding data in MVC 6 ASP.NET Core 2.2 application. Here, mainly Seeding data only is part of our scope.

Using Visual Studio 2019, I created a .NET Core 2.2 web application using the default template. Now my requirement is to seed some default data when the database is being created with Entity framework migrations.

For that purpose, we'll create a class DbInitializer.cs in the project and call its Initialize function from Startup.cs class.

Components Used

Create Project

Create your Web Application in Visual Studio 2019:

Select the Language as C# and Project type as Web, then select the first template, ASP.NET Core Web Application and click Next.

Here is how my appsettings.json looks like:

I'll be using the localhost as my server with Windows authentication.

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=localhost;Database=Mvc.SeedingData;
                          Trusted_Connection=True;MultipleActiveResultSets=true"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*"
}

Provide a project name and select the physical path and then click on Create. It'll create the project, then we'll add a new entity Terminal in the new project.

public class Terminal
{
    public int Id { get; set; }

    public string Name { get; set; }

    public DateTime CreatedDate { get; set; }
}

Here is what my DbContext class looks like:

public class ApplicationDbContext : IdentityDbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
    {

    }

    public DbSet<Terminal> Terminal { get; set; }
}

Now, we need to delete everything from the Migrations folder because we have added a new entity in the DbContext class that should be created in the database when we run the migrations and seed data.

Now, we need to run Add-migration command and give some name to the migration.

Note: Enable-migrations command is obsolete.

Now, we can run Update-database command to create the database using our code first model. Now our database will be in place but there won't be any data in the tables as of now.

DbInitializer Class

Now I've added a new class DbInitializer.cs in my project that we can call for seeding default values in the database through ApplicationDbContext.

I've added default admin role and a user so when we start the application, we can login.

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
using Mvc.SeedingData.Data;
using System;
using System.Linq;

namespace Mvc.SeedingData
{
    public static class DbInitializer
    {
        public static void Initialize(IApplicationBuilder app)
        {
            using (var serviceScope = app.ApplicationServices.CreateScope())
            {
                var context = serviceScope.ServiceProvider.GetService<ApplicationDbContext>();
                context.Database.EnsureCreated();

                var _userManager = 
                         serviceScope.ServiceProvider.GetService<UserManager<IdentityUser>>();
                var _roleManager = 
                         serviceScope.ServiceProvider.GetService<RoleManager<IdentityRole>>();

                if (!context.Users.Any(usr => usr.UserName == "demo@test.com"))
                {
                    var user = new IdentityUser()
                    {
                        UserName = "demo@test.com",
                        Email = "demo@test.com",
                        EmailConfirmed = true,
                    };

                    var userResult = _userManager.CreateAsync(user, "P@ssw0rd").Result;
                }

                if (!_roleManager.RoleExistsAsync("Admin").Result)
                {
                    var role = _roleManager.CreateAsync
                               (new IdentityRole { Name = "Admin" }).Result;
                }

                var adminUser = _userManager.FindByNameAsync("demo@test.com").Result;
                var userRole = _userManager.AddToRolesAsync
                               (adminUser, new string[] { "Admin" }).Result;


                var terminal = context.Terminal
                                  .Where(x => x.Name == "Test").FirstOrDefault();

                if (terminal == null)
                {
                    terminal = new Terminal()
                    {
                        Name = "Test",
                        CreatedDate = DateTime.Now,
                    };

                    context.Terminal.Add(terminal);
                }

                context.SaveChanges();
            }
        }
    }
}

I want to run the DbInitializer in case of Development mode only from the Startup.cs class. We need to add IdentityUser and IdentityRole into services as well.

public void ConfigureServices(IServiceCollection services)
{
    ..........

    services.AddDefaultIdentity<IdentityUser>(options =>
    {
         options.Password.RequireDigit = true;
         options.Password.RequiredLength = 6;
         options.Password.RequireNonAlphanumeric = false;
         options.Password.RequireUppercase = false;
         options.Password.RequireLowercase = false;
    })
      .AddRoles<IdentityRole>()
      .AddDefaultUI(UIFramework.Bootstrap4)
      .AddEntityFrameworkStores<ApplicationDbContext>();

     services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
     if (env.IsDevelopment())
     {
         app.UseDeveloperExceptionPage();
         app.UseDatabaseErrorPage();

         DbInitializer.Initialize(app);
     }

     ..........................
}

Now when we'll start our project under Development mode, it'll call Initialize method of DbInitializer class and insert data into the database tables.

Conclusion

We have achieved our goal of seeding default data into our database when we create our database through migrations and started our project under Development environment. We tried to limit ourselves only to the defined scope of seeding default data. All of you people are most welcome if you've any questions, Thanks for reading....

History

  • 28th July, 2019: Initial version
  • 14th August, 2019: Improved the content and added source code for downloading

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here