Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to seed in Entity Framework Core 3.0?

I am trying seed the database with some data, using ASP.NET CORE 3.0 and EF Core.

I've created my DbContext and according to documentation, online sources, or even EF Core 2.1 questions (I could not find any breaking changes on this topic).

protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Band>().HasData(
            new Band()
            {
                Id = Guid.Parse("e96bf6d6-3c62-41a9-8ecf-1bd23af931c9"),
                Name = "SomeName",
                CreatedOn = new DateTime(1980, 2, 13),
                Description = "SomeDescription"
            });

        base.OnModelCreating(modelBuilder);           
    }

This does not do what I expect: nothing is seeded on starting the application (even if during debug the method is called from somewhere).

However, if I add a migration, the migration contains the corresponding insert statement (which is not the kind of seeding I am looking for).

Question: What is the right way to have the seed of the database being performed on application start?

By seed the database, I mean that I expect some data to be ensured in some tables everytime the application is started.


I have the alternative to create a seeding class and handle it after the Database.Migrate with custom code, but this seems like a workaround, because the documentation specifies that OnModelCreating should be used to seed data).


So to my understanding after reading the answers and re-reading the documentation, what they mean by "seed" is an "initialization" which can take place right next to the data model (which is why it felt strange - mixing the model creation with the data seeding part).

like image 331
Claudiu A Avatar asked Feb 07 '20 15:02

Claudiu A


People also ask

How do I seed data in .NET core?

Net core project with Identity, Entity framework and language as C#. In Entity framework , we can define default database table values before creating database model. This concept is called seeding. We are going to use seeding in order to define default users and roles here.

Which method can be used to seed initial data in database using Entity Framework Core?

Seed Data in Entity Framework Core So as soon as we execute our migration files to create and configure the database, we want to populate it with some initial data. This action is called Data Seeding. So, we are using the HasData method to inform EF Core about the data it has to seed.

What is seed data in Entity Framework Core?

Model seed data. Unlike in EF6, in EF Core, seeding data can be associated with an entity type as part of the model configuration. Then EF Core migrations can automatically compute what insert, update or delete operations need to be applied when upgrading the database to a new version of the model.

How to create and update a database with Entity Framework Core?

This post is divided into several parts: Using migrations is a standard way to create and update a database with Entity Framework Core. The migration process has two steps: Creating migration and Applying migration.

Can seeding in EF Core be used for an application?

The seeding in EF Core is designed for migration, its initialised data for the database, not for an applications runtime. If you want a set of data to be unchanged then consider utilising an alternative method?

How to create and execute migrations with Entity Framework Core?

All we have to do is to create model classes, context class, apply configuration (which we already did) and create and execute migrations with the set of simple commands. VIDEO: Migrations and Seed Data with Entity Framework Core.


1 Answers

if you have complex seed data default EF core feature is not a good idea to use. for example, you can't add your seed data depending on your configurations or system environment.

I'm using a custom service and dependency injection to add my seed data and apply any pending migrations for the context when the application starts. ill share my custom service hopes it helps :

IDbInitializer.cs

    public interface IDbInitializer
    {
        /// <summary>
        /// Applies any pending migrations for the context to the database.
        /// Will create the database if it does not already exist.
        /// </summary>
        void Initialize();

        /// <summary>
        /// Adds some default values to the Db
        /// </summary>
        void SeedData();
    }

DbInitializer.cs

    public class DbInitializer : IDbInitializer {
        private readonly IServiceScopeFactory _scopeFactory;

        public DbInitializer (IServiceScopeFactory scopeFactory) {
            this._scopeFactory = scopeFactory;
        }

        public void Initialize () {
            using (var serviceScope = _scopeFactory.CreateScope ()) {
                using (var context = serviceScope.ServiceProvider.GetService<AppDbContext> ()) {
                    context.Database.Migrate ();
                }
            }
        }

        public void SeedData () {
            using (var serviceScope = _scopeFactory.CreateScope ()) {
                using (var context = serviceScope.ServiceProvider.GetService<AppDbContext> ()) {

                    //add admin user
                    if (!context.Users.Any ()) {
                        var adminUser = new User {
                            IsActive = true,
                            Username = "admin",
                            Password = "admin1234", // should be hash
                            SerialNumber = Guid.NewGuid ().ToString ()
                        };
                        context.Users.Add (adminUser);
                    }

                    context.SaveChanges ();
                }
            }
        }
    }

for using this service you can add it to your service collection :

 // StartUp.cs -- ConfigureServices method
 services.AddScoped<IDbInitializer, DbInitializer> ()

because i want to use this service every time my program starts i'm using injected service this way :

 // StartUp.cs -- Configure method
         var scopeFactory = app.ApplicationServices.GetRequiredService<IServiceScopeFactory> ();
         using (var scope = scopeFactory.CreateScope ()) {
            var dbInitializer = scope.ServiceProvider.GetService<IDbInitializer> ();
            dbInitializer.Initialize ();
            dbInitializer.SeedData ();
         }

like image 174
AliReza Sabouri Avatar answered Oct 20 '22 18:10

AliReza Sabouri