Vince
Vince

Reputation: 1416

Pass arguments to IDesignTimeDbContextFactory of EF Core

How can we pass arguments to dotnet ef database update?

I want to be able to update different databases with the use of arguments.

I've tried:

dotnet ef database update "Accept"

dotnet ef database update Accept

but it didn't work..

Or how I can put a switch to get different connectionString from my configuration?

public ProjectContext CreateDbContext(string[] args)
{
    IConfigurationRoot configuration = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json")
        .Build();

    // Find a way to get different connection string 
    var connectionString = configuration.GetConnectionString(args[0]);

    var builder = new DbContextOptionsBuilder<ProjectContext>();
    builder.UseSqlServer(connectionString);

    return new ProjectContext(builder.Options);
}

Upvotes: 21

Views: 8491

Answers (5)

kudoku
kudoku

Reputation: 329

Hope this answer will help people who are trying to resolve this using .net cli.

Custom arguments can be passed to IDesignTimeDbContextFactory<T> using -- token as mentioned earlier, but I found missing actual example showing that basically there is no rule how you define them, e.g. can be -- -DbUser Admin, -- DbUser=Admin. Just make sure there is a space separator following --. The rest is forwarded to design time context factory automatically.

With all this in mind the sample usage may look like:

dotnet ef database update -c YourDbContext -- -DbUser Admin -Password Secret

dotnet ef database update -c YourDbContext -- DbUser=Admin Password=Secret

Latter seems makes more sense as parameters arrive in single dimension array, so have to map param name with param value manually if you choose the first example. Also second one looks more clear to me as extra dashes make it more confusing.

More information here: learn.microsoft.com

Upvotes: 1

workabyte
workabyte

Reputation: 3775

from everything I ready here I basically ended up with CreateDbContext(string[] args) the args will get populated with anything after you initial CMD

The -- token directs dotnet ef to treat everything that follows as an argument and not try to parse them as options. Any extra arguments not used by dotnet ef are forwarded to the app. more here

will result with args being populated with 4 args this works as the -- passes the all else back to dotnet to set the args

As an example, when adding IDesignTimeDbContextFactory<YourContext> interface to your Context adds the following method and this is where I am able to pass in the vars

    public DataBaseContext CreateDbContext(string[] args)
    {
        Debugger.Launch();
        Console.WriteLine($@"Args:");
        
        foreach (var arg in args)
        {
            Console.WriteLine($"Arg: {arg}");
        }
    }

this will write out the 4 vars passed in -test something -testagain again I post this answer to help expand on other answers here and see the full context

Upvotes: 1

Ogglas
Ogglas

Reputation: 70176

You can also set variables like this:

$env:SqlConnectionString="Server=tcp:mySqlServerStuffxxx"
Add-Migration InitialCreate
Update-Database

Source:

https://dev.to/azure/using-entity-framework-with-azure-functions-50aa#adding-an-entity-framework-migration

It won't work for ConnectionStrings.DefaultConnection though. It will give the following error:

The property 'DefaultConnection' cannot be found on this object. Verify that the property exists and can be set.

Upvotes: 0

Suamere
Suamere

Reputation: 6258

.NET 5 releases in a couple weeks from the time of this answer. So this is possible to change.

Answer Now

The .NET 5, and the associated EF Core 5+ NuGets support this. In Package Manager you can type:

Add-Migration YourMigrationName -Args "Space Separated Args"
Update-Database -Args "Space Separated Args"

For example, I use this:

Update-Database -Args MyConnName

In my Startup project I have a config file (Or appsettings.json) that has that connection string key, and I pull that in.

Note I said .NET Core 5. This will be have a full release in a few weeks from now. So in a few weeks this answer may be simple. But until then, you may need to install Preview versions (And NuGet PreReleases)

Answer Prior to now

There were lacking options when this question was asked, though there were options, like using dotnet ef commands with AppArgs, as discussed here. But these have changed, and are also now accessible from PM Console as discussed in the above "Now" answer.

Upvotes: 8

Paul Michaels
Paul Michaels

Reputation: 16705

I had a similar issue recently trying to get an Asp.Net Core app to read the connection string. It turns out that you don't need the IDesignTimeDbContextFactory. Instead, just make sure that your context has a paramerless constructor, and use something like this in the startup:

services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(
        Configuration.GetConnectionString("DefaultConnection")));

This should resolve to whichever connection string you have configured. If you did want to use two separate connections at the same time (which I realise you didn't want), you could do this by registering multiple DbContexts at this point; for example:

services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(
        Configuration.GetConnectionString("DefaultConnection")));

services.AddDbContext<MyDbContext>(options =>
    options.UseSqlServer(
        Configuration.GetConnectionString("OtherConnection")));

Upvotes: 0

Related Questions