57

Is there any code to perform automatic migration in Entity Framework core code first in asp.net core project?

I do it simply in MVC4/5 by adding

Database.SetInitializer(new MigrateDatabaseToLatestVersion<AppDbContext, MyProject.Migrations.Configuration>());
public Configuration() {
          AutomaticMigrationsEnabled = true;
        }

This saves time when entities changed

Sampath
  • 63,341
  • 64
  • 307
  • 441
Lapenkov Vladimir
  • 3,066
  • 5
  • 26
  • 37

10 Answers10

54

You can call context.Database.Migrate()in your Startup.cs

eg:

using (var context = new MyContext(...))
{
    context.Database.Migrate();
}
Frank Odoom
  • 1,545
  • 18
  • 19
  • 2
    MyContext looks this way , I don't know what to put in options public ApplicationDbContext(DbContextOptions options) : base(options) { } – Lapenkov Vladimir Sep 16 '16 at 09:45
  • Refer to this article to see how you can manually configure your context http://stackoverflow.com/questions/38417051/what-goes-into-dbcontextoptions-when-invoking-a-new-dbcontext and https://github.com/aspnet/EntityFramework/issues/6493 – Frank Odoom Sep 16 '16 at 09:49
  • 1
    I do the following way in Startup.cs : Startup::Configure after defining routes i add : var options = new DbContextOptionsBuilder(); options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")); using (var context = new ApplicationDbContext(options.Options)) { context.Database.Migrate(); } but this doesn't perform migrations – Lapenkov Vladimir Sep 16 '16 at 10:15
  • Register your context with dependency injection https://docs.efproject.net/en/latest/platforms/aspnetcore/new-db.html – Frank Odoom Sep 16 '16 at 10:44
  • I registered it this way : services.AddDbContext(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); – Lapenkov Vladimir Sep 16 '16 at 10:49
  • download a simple sample from this repository..this uses Package Manager Console Scripts...hope it helps :-) https://github.com/dotnetjalps/EntityFrameworkCoreMigration – Frank Odoom Sep 16 '16 at 10:57
  • 17
    @FrankOdoom Answer is wrong, unless individual migration steps are added, Migration does not work and it is not equivalent of `AutomaticMigrationsEnabled` – Akash Kava Nov 06 '17 at 20:30
  • context.Database.Migrate(); will update the database based on the migrations you have created.So do not forget to add migrations. – karunakar bhogyari Feb 29 '20 at 07:51
40

EF core doesn't support automatic migrations.So you have to do it manually.

From the perspective of automatic migrations as a feature, we are not planning to implement it in EF Core as experience has showed code-base migrations to be a more manageable approach.

You can read full story here : Not to implement Automatic Migrations

Sampath
  • 63,341
  • 64
  • 307
  • 441
  • 7
    Be that as it may, it worked perfectly for me in all the projects I worked on, resulting in extremely low-fuss maintenance especially during the build-up of a project. Shame that it is gone, but I can imagine sometimes the overhead wasn't worth it. – Arwin Oct 08 '16 at 14:06
  • Still no chance for automatic migrations to be supported in EF Core 2.0 in Sep. 2017? – Afshar Mohebi Sep 16 '17 at 08:08
  • Maybe this helps: @Afshar https://github.com/aspnet/EntityFrameworkCore/issues/8045 – Sampath Sep 16 '17 at 09:18
  • Thank you @Sampath, the link provides an alternative instead of automatic migrations, if I am understanding correctly. My team needs automatic migration in production enviroment rather than dev environment. – Afshar Mohebi Sep 16 '17 at 09:37
  • Oh..OK, Actually I'm not using this tech stack now due to now I'm working only on Ionic mobile apps.But according to my post's link, they labeled it as `closed-wont-fix` @Afshar – Sampath Sep 16 '17 at 09:46
  • @Sampath What you consider as "Automatic Migrations" is not what is meant by this question. Here, what they mean is "to update the database on the production server on the first run of the application, whenever the developer makes a change to the data structure by creating and running a manual migration", which could be simply done (as is mentioned in other answers here), but the thing EF Core does not support, is, "to update the database automatically whenever there's a change in the data structure, without creating a manual migration". There's a big difference between the two! – Ali Dehghan Tarzeh Dec 11 '19 at 10:11
  • Here's a link to the full instructions for running the manually-created migrations on the server automatically: https://blog.rsuter.com/automatically-migrate-your-entity-framework-core-managed-database-on-asp-net-core-application-start/ – Ali Dehghan Tarzeh Dec 11 '19 at 10:32
  • @AliDehghanTarzeh Those are not official. See the official link: https://github.com/aspnet/EntityFrameworkCore/issues/6214 – Sampath Dec 11 '19 at 13:05
27

This is the way they do it in IdentityServer4 http://identityserver.io

public void ConfigureServices(IServiceCollection services)
{
    var connectionString = Configuration.GetConnectionString("DefaultConnection");
    var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;

    // Add framework services.
    services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(connectionString));
    ...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    // this will do the initial DB population
    InitializeDatabase(app);
}

private void InitializeDatabase(IApplicationBuilder app)
{
    using (var scope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
    {
        scope.ServiceProvider.GetRequiredService<ApplicationDbContext>().Database.Migrate();
        scope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();
        ...
    }
}
Matt Morgan
  • 360
  • 3
  • 9
20

Automatic migrations is not supported in EF Core. Migration it is necessary to create hands. To automatically apply all existing handmade migrations need to add the following code in the class Program:

public class Program
{
    public static void Main(string[] args)
    {
        var host = CreateWebHostBuilder(args).Build();

        using (var scope = host.Services.CreateScope())
        {
            var services = scope.ServiceProvider;

            try
            {
                var context = services.GetRequiredService<MyDbContext>();
                context.Database.Migrate(); // apply all migrations
                SeedData.Initialize(services); // Insert default data
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occurred seeding the DB.");
            }
        }

        host.Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}
Mentor
  • 3,058
  • 1
  • 22
  • 27
  • 1
    Why are you using an array if you only access the element at 0? – ProfK May 23 '17 at 05:52
  • 6
    in order to have one field for the lock and a quick check without unboxing. – Mentor May 25 '17 at 14:20
  • 1
    This is a duplicate of @Matt-Morgan's answer above. Although the timestamp of your original answer is 2017-02-17, you added the scoped dependency injected dbcontext solution in 2018-06-07, while Matt published the same answer 2017-04-20. – Daniel Aug 15 '20 at 17:01
6

Following Microsoft's documentation

https://learn.microsoft.com/en-us/aspnet/core/data/ef-mvc/intro

If you are using dependency injection, first, you need to setup a static class Data/DbInitializer.cs and add the following code:

public static class DbInitializer
{
    public static void Initialize(ApplicationDbContext context)
    {
        context.Database.Migrate();

        // Add Seed Data...
    }
}

Notice, this is also where you can add seed data.

Next, in your Program.cs file, add the following code

public static void Main(string[] args)
    {
        var host = BuildWebHost(args);

        using (var scope = host.Services.CreateScope())
        {
            var services = scope.ServiceProvider;
            try
            {
                var environment = services.GetRequiredService<IHostingEnvironment>();

                if (!environment.IsDevelopment())
                {
                    var context = services.GetRequiredService<ApplicationDbContext>();
                    DbInitializer.Initialize(context);
                }
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occurred while seeding the database.");
            }
        }

        host.Run();
    }

In my case, I'm checking the environment to make sure I'm in development so I can control the migrations/updates. However, in production, I want them to be automatic for continuous integration. As others have mentioned, this is probably not best practices but on small projects it works great.

Amac
  • 158
  • 1
  • 8
6

You can call Database.Migrate() in db context constructor.

Evgeniy P
  • 71
  • 1
  • 2
5

My working automigration code Asp Net Core 2.0.7.

    // startup.cs
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        // configure app

        SeedData.Initialize(app.ApplicationServices);
    }       

    // dbInitializer.cs
    public static class SeedData
    {
        public static void Initialize(IServiceProvider serviceProvider)
        {
            using (var serviceScope = serviceProvider.CreateScope())
            {
                var context = serviceScope.ServiceProvider.GetService<ApplicationDbContext>();

                // auto migration
                context.Database.Migrate();

                // Seed the database.
                InitializeUserAndRoles(context);
            }
        }

        private static void InitializeUserAndRoles(ApplicationDbContext context)
        {
            // init user and roles  
        }
    }
dev-siberia
  • 2,746
  • 2
  • 21
  • 17
2

If the model changes a lot and you manage a medium - large team, migrations leads more problems than solution at least in development phase. I published a nuget package with automatic migration for .net core, EFCore.AutomaticMigrations - https://www.nuget.org/packages/EFCore.AutomaticMigrations/, so manual migration not needed anymore.

You can call directly in Program class, like bellow:

 public static void Main(string[] args)
    {
        var host = CreateWebHostBuilder(args);

        using (var scope = host.Services.CreateScope())
        {
            var services = scope.ServiceProvider;
            var loggerFactory = services.GetRequiredService<ILoggerFactory>();
            var logger = loggerFactory.CreateLogger<Program>();
            try
            {
                var environment = services.GetRequiredService<IWebHostEnvironment>();

                if (environment.IsDevelopment())
                {
                    var context = services.GetRequiredService<ApplicationContext>();
                    MigrateDatabaseToLatestVersion.ExecuteAsync(context).Wait();
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "An error occurred creating/updating the DB.");
            }
        }

        host.Run();
    }
Ionut N
  • 434
  • 4
  • 9
1

Frank Odoom's answer works even 4 years later in .net 5, but it is not the intended context to call the migration at runtime... And, it appears it never was because it requires us to mock the DbContext with DbContextOptions whos documentation explicitly states:

"The options to be used by a DbContext. You normally override OnConfiguring(DbContextOptionsBuilder) or use a DbContextOptionsBuilder to create instances of this class and it is not designed to be directly constructed in your application code."

Here is my suggestion:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
       // database provider is configured before runtime migration update is applied e.g:
       optionsBuilder.UseSqlServer(ConnectionString);
       Database.Migrate();
}

Edit: My suggestion is actually horrible if you are using multiple DBContexts in the same project... It would migrate the database multiple times. Which would most likely not break anything, but it would slow startup considerably.

  • I've got this when trying to call Database.Migrate() inside OnConfiguring: "System.InvalidOperationException: 'An attempt was made to use the context instance while it is being configured. A DbContext instance cannot be used inside 'OnConfiguring' since it is still being configured at this point. This can happen if a second operation is started on this context instance before a previous operation completed. Any instance members are not guaranteed to be thread safe." – mrNone Dec 29 '22 at 08:53
  • That makes sense. My use case was very Single DBContext specific. It would be smart for newer versions of .net to implement a failsafe that wouldn't allow it under circumstances where there are multiple contexts. If you're still looking for a way to do it: this is what worked for me for .net6 https://jasonwatmore.com/post/2022/02/01/net-6-execute-ef-database-migrations-from-code-on-startup Much more elegant too. – Mikie Sterner Jan 19 '23 at 18:19
0

my best advice is not to use the automatic migration.It is always better to add migrations manually and also avoid bulk migration and stick to best practice for using manual migration

automatic migration is not a magic tool and there will be several occasions where you might want to add some addition changes to the migration. You only accomplish by using manual migration.

To enable migration, type "enable-migrations" in the package manager console

This way you will have full control of upgrading or downgrading your database and also easy to track migrations.

Just three simple steps in package manager console.

1) add-migrations [some name for your migration]

2) migrations is generated for the changes, you review them and also can make changes to it

3) update-database your migration is complete now.

handling migration is less painful!

srini
  • 170
  • 4
  • 5
    When the model changes a lot and and multiple people work on the same project, migrations leads more problems than solutions. Moreover, having thousands of migrations makes the build slower and complicated for no reason. In this context, automatic migration seems the more reasonnable approach. – eka808 Aug 20 '18 at 09:41