Data Seeding in Entity Framework Core 2.1

As is the way with things in life, last week I was working on a project where I wanted to seed data in EF Core 2.0. Unfortunately there was no method built in to seed data, so I rolled my own, and got it working. This week EF Core 2.1 was released and one of the new features is built in data seeding. I really like they way the implemented it as part of the modelbuilder. Here I am going to give an example of how I used it with my security model. I have a UserInformation table, a UserRole table, and a UserInformationUserRole table to handle the many to many relationship. Unfortunately EF Core still doesn't handle many to many relationships through navigation properties, but it isn't too much of a headache to wire things together with an intermediary table. Here are the model classes that I have setup.

Model

The classes in this folder define the model for the security users.
UserInformation.cs This class is used to define the user information which is associated with the user's lan id.
public class UserInformation
    {
        [Key]
        public int UserInformationId { get; set; }

        [MaxLength(25),Display(Name = "LAN ID")]
        public String LanId { get; set; }

        [MaxLength(25), Display(Name = "First Name")]
        public string FirstName { get; set; }

        [MaxLength(25), Display(Name = "Last Name")]
        public string LastName { get; set; }

        [MaxLength(100)]
        public string Email { get; set; }

        public bool Enabled { get; set; }

        public virtual ICollection<UserInformationUserRole> UserInformationUserRoles { get; set; }   
    }
UserRole.cs This class is used to define the application roles.
public class UserRole
    {
        [Key]
        public int UserRoleId { get; set; }

        [MaxLength(25)]
        public string Name { get; set; }

        [MaxLength(100)]
        public string Description { get; set; }

        public virtual ICollection<UserInformationUserRole> UserInformationUserRoles { get; set; }
    }
UserInformationUserRole.cs This class us used to define the many to many relationship between user information and user role.
public class UserInformationUserRole
    {
        public int UserInformationId { get; set; }
        public UserInformation UserInformation { get; set; }
        public int UserRoleId { get; set; }
        public UserRole UserRole { get; set; }
    }
In my context file, I have the fluent configuration to setup the many to many relationship followed by the methods for seeding data.
protected override void OnModelCreating(ModelBuilder modelBuilder)
        {

            //Build the many to many relationship between users and roles
            modelBuilder.Entity<UserInformationUserRole>()
                .HasKey(ir => new { ir.UserInformationId, ir.UserRoleId });

            modelBuilder.Entity<UserInformationUserRole>()
                .HasOne(ir => ir.UserInformation)
                .WithMany(ui => ui.UserInformationUserRoles)
                .HasForeignKey(ir => ir.UserInformationId);

            modelBuilder.Entity<UserInformationUserRole>()
                .HasOne(ir => ir.UserRole)
                .WithMany(ur => ur.UserInformationUserRoles)
                .HasForeignKey(ir => ir.UserRoleId);


            //Use the new HasData to seed the database with values.
            modelBuilder.Entity<UserRole>().HasData(
                new UserRole {UserRoleId = 1,Name = "Administrators", Description = "Users with admin access"},
                new UserRole {UserRoleId = 2,Name = "Users", Description = "Users with base level Access"}
            );

            modelBuilder.Entity<UserInformation>().HasData(
                new UserInformation { UserInformationId = 1,LanId = "domain\\User1",FirstName = "First1",LastName = "Last1", Email = "name1@domain.com", Enabled = true },
                new UserInformation { UserInformationId = 2,LanId = "domain\\User2", FirstName = "First2", LastName = "Last2", Email = "name2@domain.com", Enabled = true },
                new UserInformation { UserInformationId = 3,FirstName = "First3", LastName = "Last3", LanId = @"domain\User3", Email = "name3@domain.com", Enabled = true }
                );

            modelBuilder.Entity<UserInformationUserRole>().HasData(
                new UserInformationUserRole {UserInformationId = 1, UserRoleId = 1},
                new UserInformationUserRole {UserInformationId = 2, UserRoleId = 2},
                new UserInformationUserRole {UserInformationId = 3, UserRoleId = 1}
            );
That's all there is to it. When you add your migration and update the database, your tables will be populated with the new data.

Comments

Popular posts from this blog

Asp.Net Core with Extended Identity and Jwt Auth Walkthrough

File Backups to Dropbox with PowerShell

ASP.NET Core 2.1 Windows Authentication with DB Roles for Authorization Part 1