In this session, we discuss Seed Data in Entity Framework Core and sync Domain Models with the database. Also, we will show you how you can remove a migration that was already synced with the database. During this session, we implement seeding data with two methods. First, we seed data inside the DB context, and then we use the ModelBuilder extension.
Seed Data inside DB Context in EF Core
For this purpose, we need to override OnModelCreating inside DB Context.
1 2 3 4 5 6 7 8 |
protected override void OnModelCreating(ModelBuilder modelBuilder) { } |
Then, with the object of ModelBuilder and HasData method, we can seed the data.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public static void Seed(this ModelBuilder modelBuilder) { modelBuilder.Entity<Category>().HasData( new Category { ID = 1, CategoryName = "Bill", Description = "This categoroy is assigned for recording Bill cost", Active = CategoryActiveOptions.Yes }); } |
For syncing the changes and seeding the data to the Database, we need to run Add-Migration and Update-Database commands that we already discussed.
Seed Data with ModelBuilder Extension
To keep DB Context as clear as possible, we can move Seeding Data inside an extension of ModelBuilder. Thus, we need to create a Public Static class which should have a Public Static Void method that has an object of ModelBuilder as an input parameter.
1 2 3 4 5 6 7 8 9 10 11 |
public static class SeedExtension { public static void Seed(this ModelBuilder modelBuilder) { } } |
Then, as shown above, with the object of ModelBuilder and HasData method, we can seed the data.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public static class SeedExtension { public static void Seed(this ModelBuilder modelBuilder) { modelBuilder.Entity<Category>().HasData( new Category { ID = 1, CategoryName = "Bill", Description = "This categoroy is assigned for recording Bill cost", Active = CategoryActiveOptions.Yes }); } } |
Also, we need to call this extension inside the DB Context class.
1 2 3 4 5 6 7 8 |
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Seed(); } |
Also, as mentioned we need to run Add-Migration and Update-Database commands to sync the changes with the Database.
Sync Domain Models with Database in EF Core
During the development of a project, we need to modify the Domain Models based on our requirements. Hence, we need to sync these changes with the Database to have a unified structure on both sides. In EF Core, as we discussed in detail earlier, we should apply the changes to the database with Add-Migration and UpdateDatabase command.
When we run the Add-Migration command, EF Core creates a Class that contains Up and Down methods. Also, EF Core updated the Snapshot class based on the latest Model changes. Next, in the case of launching Update-Database, Up method of the created class is embarked and the changes will be applied to the Database. But, if we run the Remove-Migration command, the Snapshot class changes will be reverted and the auto-generated migration file will be deleted.
For better understanding, you can see a sample of the auto-generated Migration class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
using Microsoft.EntityFrameworkCore.Migrations; #nullable disable namespace DailyCostWebApplication.Migrations { public partial class AddInvoiceImagePathtoCost : Migration { protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.AddColumn<string>( name: "InvoiceImagePath", table: "Costs", type: "nvarchar(max)", nullable: true); } protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropColumn( name: "InvoiceImagePath", table: "Costs"); } } } |
Moreover, you can see a sample of the Snapshot class below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
// <auto-generated /> using System; using DailyCostWebApplication.Models; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; #nullable disable namespace DailyCostWebApplication.Migrations { [DbContext(typeof(WebAppDBContext))] partial class WebAppDBContextModelSnapshot : ModelSnapshot { protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder .HasAnnotation("ProductVersion", "6.0.2") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); modelBuilder.Entity("DailyCostWebApplication.Models.Category", b => { b.Property<int>("ID") .ValueGeneratedOnAdd() .HasColumnType("int"); SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("ID"), 1L, 1); b.Property<int>("Active") .HasColumnType("int"); b.Property<string>("CategoryName") .IsRequired() .HasColumnType("nvarchar(max)"); b.Property<string>("Description") .HasColumnType("nvarchar(max)"); b.HasKey("ID"); b.ToTable("Categories", (string)null); b.HasData( new { ID = 1, Active = 0, CategoryName = "Bill", Description = "This categoroy is assigned for recording Bill cost" }, new { ID = 2, Active = 0, CategoryName = "Gerocery", Description = "This categoroy is assigned for recording Gerocery cost" }, new { ID = 3, Active = 0, CategoryName = "Rent", Description = "This categoroy is assigned for recording Rental cost" }); }); modelBuilder.Entity("DailyCostWebApplication.Models.Cost", b => { b.Property<int>("ID") .ValueGeneratedOnAdd() .HasColumnType("int"); SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("ID"), 1L, 1); b.Property<decimal>("Amount") .HasColumnType("decimal(18,2)"); b.Property<int>("CategoryID") .HasColumnType("int"); b.Property<string>("Comment") .HasMaxLength(150) .HasColumnType("nvarchar(150)"); b.Property<string>("InvoiceImagePath") .HasColumnType("nvarchar(max)"); b.Property<int>("PaymentMethod") .HasColumnType("int"); b.Property<DateTime>("RegisteredDate") .HasColumnType("datetime2"); b.HasKey("ID"); b.HasIndex("CategoryID") .IsUnique(); b.ToTable("Costs", (string)null); }); modelBuilder.Entity("DailyCostWebApplication.Models.Cost", b => { b.HasOne("DailyCostWebApplication.Models.Category", "Category") .WithOne("Cost") .HasForeignKey("DailyCostWebApplication.Models.Cost", "CategoryID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("Category"); }); modelBuilder.Entity("DailyCostWebApplication.Models.Category", b => { b.Navigation("Cost"); }); #pragma warning restore 612, 618 } } } |
Remove Synced Migration in EF Core
Normally, we can not remove a Migration that is already applied to the Database. Thus, we need to revert the applied changes from the Database. We can see the history of Migrations inside the EFMigrationsHistory table. Hence, we can find the name of the stage that we want to be reverted from that Table. Next, we can run the Update-Database command with the Migration Name to revert the changes that were applied after that migration. Thereupon, we can remove the Migrations with the Remove-Migration command.
Remove-Migration command removes the latest added migration each time.
If you need more details, watch this session video. Also, for being updated about our coming sessions, follow us on Instagram, Facebook, Telegram, or YouTube. Moreover, you can have access to the list of all sessions HERE and you can download this session source code from our GitHub.
You can download this Session Slides form HERE.