Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Migrations in Entity Framework Core 2.0 - How to specify environment or pass arguments

I'm playing with EF Core 2.0 and have 3 env in my app: dev, staging and prod. Now I want to apply db schema to specific database. However I faced with a problem. When I executing dotnet ef database drop (update) for example, it's trying to get production env by default.

How could I specify what environment should be used? My DbContextFactory looks like that:

public class MyDbContextFactory : IDbContextFactory<MyDbContext>
    {
        public MyDbContext Create(string[] args) => //how to pass something to this args?
            WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .Build().Services.GetRequiredService<MyDbContext>();
    }

it was something like: dotnet ef database drop -e development in version 1.1, but this was removed from version 2.0.

set ASPNETCORE_ENVIRONMENT=development dotnet ef database drop

also seems not working.

like image 295
silent_coder Avatar asked Jun 08 '17 17:06

silent_coder


People also ask

How do you specify context in migration?

Using multiple context types One way to create multiple migration sets is to use one DbContext type per provider. Specify the context type when adding new migrations. You don't need to specify the output directory for subsequent migrations since they are created as siblings to the last one.

How do I use migrations in Entity Framework?

Step 1 − Before running the application you need to enable migration. Step 2 − Open Package Manager Console from Tools → NuGet Package Manger → Package Manger Console. Step 3 − Migration is already enabled, now add migration in your application by executing the following command.

How do I update my database in migration?

After creating a migration file using the add-migration command, you have to update the database. Execute the Update-Database command to create or modify a database schema. Use the –verbose option to view the SQL statements being applied to the target database.

Can we have multiple DbContext in Entity Framework?

Multiple DbContext was first introduced in Entity Framework 6.0. Multiple context classes may belong to a single database or two different databases.


2 Answers

What I gathered from here is that the -e MyCustomEnvironment is not available in the EF Core Design Tools for Core 2.x


To set Environment Variables I discovered you have the following choices depending on your usecase

Environment Variable for this CMD Session (Windows):

set ASPNETCORE_ENVIRONMENT <Environment Name>

Environment Variable in your User Environment (Windows):

setx ASPNETCORE_ENVIRONMENT <Environment Name>

Also possible via GUI (Windows)

"Start" -> "Edit the system environment Variables" -> "Environment Variables" -> "New"

Environment Variable for this Shell session (Linux):

export ASPNETCORE_ENVIRONMENT=<Environment Name>

Environment Variable in you User Environment (Linux):

cd ~ echo 'export ASPNETCORE_ENVIRONMENT=<Environment Name>' >> .bashrc This will actually export the Variable everytime .bashrc is executed. I'm not sure if this is the way to go on Linux but it worked for me.


Also in my case I didn't want the StartUp code to run since I feel like for a DesignTime action its not neccessary to register all the Services etc of my Application. This could be done like so:

        var basePath = AppDomain.CurrentDomain.BaseDirectory;

        var envName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");

        var builder = new ConfigurationBuilder()
            .SetBasePath(basePath)
            .AddJsonFile("appsettings.json")
            .AddJsonFile($"appsettings.{envName}.json", true)
            .AddEnvironmentVariables();

        var config = builder.Build();

        var customOptions = config.GetSection("database").Get<DatabaseOptions>();


Also if you have more complex szenarios you now might want to create some small batch or shell skripts

like image 136
D4rth B4n3 Avatar answered Oct 25 '22 12:10

D4rth B4n3


Well, to be honest I don't know exact answer for that question. I think environment variables should work, but the way how you set them are pretty much depend from environment you working for. So it will be one story on linux, different for on Windows (again different for PowerShell) and something elso on MacOS.

this works for me on Linux and in bash console on Windows:

ASPNETCORE_ENVIRONMENT="{NAME_OF_ENV}";dotnet ef {somecommand you want to execute}

In Powershell you could try something like that:

$env:ASPNETCORE_ENVIRONMENT="{NAME_OF_ENV}"
dotnet ef {somecommand you want to execute}

However, even it's migration, it's still a console app inside. So you could just ask user to enter environment from console with something like:

Console.WriteLine("Enter environment you want to use");
var env = Console.ReadLine();
WebHost.CreateDefaultBuilder(args)
       .UseEnvironment(env)
       .UseStartup<Startup>()
       .Build().Services.GetRequiredService<MyDbContext>();

This is of course not a perfect solution, but if you out of options - this could be a workaround. You could pass other param that way as well.

like image 32
Ph0en1x Avatar answered Oct 25 '22 13:10

Ph0en1x