Click here to Skip to main content
14,355,411 members

Seeding Data MVC 6 .NET Core Application

Rate this:
3.52 (9 votes)
Please Sign up or sign in to vote.
3.52 (9 votes)
14 Aug 2019CPOL
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:

Image 1

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

Image 2

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.

Image 3

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.

Image 4

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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

dnxit
Software Developer
Pakistan Pakistan
No Biography provided

Comments and Discussions

 
QuestionWhere is the source code (solution file)? Pin
mehtar4-Aug-19 23:19
membermehtar4-Aug-19 23:19 
AnswerRe: Where is the source code (solution file)? Pin
dnxit7-Aug-19 20:50
memberdnxit7-Aug-19 20:50 
AnswerRe: Where is the source code (solution file)? Pin
dnxit14-Aug-19 22:16
memberdnxit14-Aug-19 22:16 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Article
Posted 14 Aug 2019

Stats

4.8K views
75 downloads
12 bookmarked