How to Pass CreateDbContext Args Parameters? - entity-framework-core

I have a multiple DBContexts and DesignTimeDbContextFactory implementation like below.
public class MasterDbContextFactory : IDesignTimeDbContextFactory<MasterDbContext>
{
public MasterDbContext CreateDbContext(string[] args)
{
StringBuilder sb = new StringBuilder();
foreach (var arg in args)
sb.AppendLine(arg);
System.IO.File.WriteAllText("D:\\debug.txt", sb.ToString());
string server = args[1];
string databaseName = args[2];
string connectionString = string.Format(Constant.Connection, server, databaseName);
var optionsBuilder = new DbContextOptionsBuilder<MasterDbContext>();
optionsBuilder.UseSqlServer("connection string");
return new MasterDbContext(optionsBuilder.Options);
}
}
As mentioned here, I apply like this.
Update-Database -Context MasterDbContext -AppArgs 'LAPTOP-E4UBP70J' 'MASTER_USER'
But I don't see all args parameters.

The feature is only available in recent release EF Core 5.0 Preview 6
Flow arguments into IDesignTimeDbContextFactory
Arguments are now flowed from the command line into the CreateDbContext method of IDesignTimeDbContextFactory. For example, to indicate this is a dev build, a custom argument (e.g. dev) can be passed on the command line:
dotnet ef migrations add two --verbose --dev

This work well at 5.0.0-preview.7.20365.15 version.
Adding migration with additional args:
Add-Migration InitialCreate -Context MasterDbContext -OutputDir Migrations\Master -Args 'P1 P2'
Updating migration with additional args:
Update-Database -Context MasterDbContext -Args 'P1 P2'
Here is source

Using Entity Framework Core .NET Command-line Tools version 5.0.7 or newer you can pass custom 'application arguments' into the CreateDbContext method by appending -- to the end of the command, followed by a space and then your arguments.
e.g. dotnet ef database update --context MyContext -- MyFirstArg MySecondArg
See
https://github.com/dotnet/efcore/issues/8332#issuecomment-644918706 which describes how to pass arguments when using both Command-Line and Powershell commands.
Command-Line
The commands will no longer interpret any extraneous arguments as application arguments. Instead, if you want to call a dotnet ef command with application arguments, you must now put -- after you pass in all the normal arguments, followed by whatever you want to the application arguments to be. All arguments after the -- will be interpreted as application arguments. If you need to pass in an application argument which, for instance, contains a space you will need to quote that argument e.g.
dotnet ef migrations add InitialCreate -- FirstAppArg "This is all the second application argument" ThirdAppArg

Related

How to deploy the Sql files to Dedicated Server with Azure Devops Pipeline CI/CD

I am working on Azure DevOps CI CD Pipelines. The project's Backend is Dotnet Core, Frontend is Angular 8 and for Database, we used Entity Framework code-first approach. I was able to add Front and back end in pipelines. Now I am stuck with database deployment. since I was also unable to find any dedicated article.
The project is consists of Multi Context and Multi-Project. Reference folder structure
At local we usually run this command to generate migration and it works fine.
Add-Migration -Context ABCCompanyContext AddCompanyTable
Now, in Pipeline i have added the following command which I get from stackoverflow it self. but it didn't work. But from the error. it seems like I am really close
Pipeline Command
dotnet tool install --global dotnet-ef dotnet ef migrations script -i
-o $(Build.ArtifactStagingDirectory)\Migrations\migrate.sql --project **/ABC.Company.Data.csproj --startup-project **/ABC.Company.Api.csproj -i -o $(Build.ArtifactStagingDirectory)\Migrations\migrate.sql
Error Log
2020-12-24T06:49:27.0265041Z ========================== Starting
Command Output ===========================
2020-12-24T06:49:27.0688206Z ##[command]"C:\windows\system32\cmd.exe"
/D /E:ON /V:OFF /S /C "CALL
"D:\a_temp\f3a33029-4f61-404f-9b64-c73c5296123a.cmd""
2020-12-24T06:49:32.9358440Z You can invoke the tool using the
following command: dotnet-ef 2020-12-24T06:49:32.9359182Z Tool
'dotnet-ef' (version '5.0.1') was successfully installed.
2020-12-24T06:49:38.4701578Z System.IO.IOException: The filename,
directory name, or volume label syntax is incorrect. :
'D:\a\1\s*\obj' 2020-12-24T06:49:38.4702878Z at
System.IO.FileSystem.CreateDirectory(String fullPath, Byte[]
securityDescriptor) 2020-12-24T06:49:38.4703503Z at
System.IO.Directory.CreateDirectory(String path)
2020-12-24T06:49:38.4704199Z at
Microsoft.EntityFrameworkCore.Tools.Project.FromFile(String file,
String buildExtensionsDir, String framework, String configuration,
String runtime) 2020-12-24T06:49:38.4705029Z at
Microsoft.EntityFrameworkCore.Tools.RootCommand.Execute(String[] _)
2020-12-24T06:49:38.4705729Z at
Microsoft.EntityFrameworkCore.Tools.Commands.CommandBase.<>c__DisplayClass0_0.b__0(String[]
args) 2020-12-24T06:49:38.4706399Z at
Microsoft.DotNet.Cli.CommandLine.CommandLineApplication.Execute(String[]
args) 2020-12-24T06:49:38.4707003Z at
Microsoft.EntityFrameworkCore.Tools.Program.Main(String[] args)
2020-12-24T06:49:38.4707626Z The filename, directory name, or volume
label syntax is incorrect. : 'D:\a\1\s*\obj'
2020-12-24T06:49:38.6646502Z ##[error]Cmd.exe exited with code '1'.
2020-12-24T06:49:38.7627325Z ##[section]Finishing: Build EfCore
Migrations
The error message,
System.IO.IOException: The filename, directory name, or volume label syntax is incorrect. : 'D:\a\1\s\*\obj'
The path string contains the character '*'. Normally this character is not available in file name and folder name.
As the introduction from the docs about .NET Core CLI, the values of the options '--project' and '--startup-project' are the relative paths to the project folders.
According to my test, in the 'dotnet ef' command, it seems does not support wildcard patterns.
When I use wildcard patterns to set the path values, it always return the same error message.
System.IO.IOException: The filename, directory name, or volume label syntax is incorrect. : 'D:\a\1\s\**\obj'
However, when I directly provide the complete relative paths instead of using wildcard patterns, the error disappears.
So, I recommend you directly use the complete relative paths to the project folders.

What are the rules for expected values to the dotnet ef commands?

In an ASP.NET Core application with migrations, running update database gives the following output. It works, and the verbose output displays the default values for a variety of options.
dotnet ef --verbose database update
Setting the data directory to 'C:\temp\bin\Debug\netcoreapp1.0\'.
Invoking dependency command 'Microsoft.EntityFrameworkCore.Design' in project '2016-101DP-TreeGame-Auth'
Running C:\Program Files\dotnet\dotnet.exe exec
--runtimeconfig C:\temp\bin\Debug\netcoreapp1.0\temp.runtimeconfig.json
--depsfile C:\temp\bin\Debug\netcoreapp1.0\temp.deps.json
--additionalprobingpath C:\Users\me\.nuget\packages C:\Users\me\.nuget\packages\Microsoft.EntityFrameworkCore.Design\1.0.0-preview2-final\lib\netcoreapp1.0\Microsoft.EntityFrameworkCore.Design.dll
--assembly C:\temp\bin\Debug\netcoreapp1.0\temp.dll
--startup-assembly C:\temp\bin\Debug\netcoreapp1.0\temp.dll
--dispatcher-version 1.0.0-preview2-21431
--data-dir C:\temp\bin\Debug\netcoreapp1.0\
--project-dir C:\temp
--content-root-path C:\temp
--root-namespace temp
--verbose update database
Process ID: 12544
Finding DbContext classes...
Using context 'ApplicationDbContext'.
Done.
When I try to run the same command with options, the CLI complains that my options have "unexpected values." Here are two examples.
dotnet ef --data-dir C:\temp\bin\Debug\netcoreapp1.0\ --verbose database update
dotnet ef --data-dir "C:\temp\bin\Debug\netcoreapp1.0\" --verbose database update
Both tell me this:
Microsoft.Extensions.CommandLineUtils.CommandParsingException: Unexpected value 'C:\temp\bin\Debug\netcoreapp1.0\' for option 'data-dir'
at Microsoft.Extensions.CommandLineUtils.CommandLineApplication.Execute(String[] args)
at Microsoft.EntityFrameworkCore.Tools.Cli.Program.Main(String[] args)
What are the rules for expected values to the dotnet ef commands?
There are two layers. dotnet-ef reads metadata from the project (and builds it) then calls ef using that metadata (including the output assembly paths). You cannot specify the following options from dotnet ef since they are determined for you.
--assembly
--startup-assembly
--data-dir
--project-dir
--content-root-path
--root-namespace
The rest of the options that show up in dotnet ef --help can be specified on dotnet ef.
This should get better as part of issue #6592.
Here is some documentation about dotnet ef.

EntityFramework Core database scaffolding (.NET Core RC2)

I try to create an EntityFramework Core's model with an existing database (doc here : https://docs.efproject.net/en/latest/platforms/aspnetcore/existing-db.html) but I have an error.
When I try the Package Manager method, I have the error :
The term "MY_DATABASE_NAME" is not recognize as a valid command applet [...]
This is the command I execute :
Scaffold-DbContext "'MY_CONNECTION_STRING'" Microsoft.EntityFrameworkCore.SqlServer -outputDir MY_PATH -verbose
And when I try the Command Prompt method, I have this error :
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.EntityFrameworkCore.Tools.DispatchCommand.<>c__DisplayClass2_0.<Create>b__0()
at Microsoft.Extensions.CommandLineUtils.CommandLineApplication.Execute(String[] args)
at Microsoft.EntityFrameworkCore.Tools.Program.Main(String[] args)
Object reference not set to an instance of an object.
Here the command I execute :
dotnet ef dbcontext scaffold "'MY_CONNECTION_STRING'" Microsoft.EntityFrameworkCore.SqlServer -outputDir MY_PATH -verbose
Before this question, I checked :
If I have installed good packages (Microsoft.EntityFrameworkCore.SqlServer, Microsoft.EntityFrameworkCore.Tools and Microsoft.EntityFrameworkCore.SqlServer.Design)
If my project.json was correct (tools, ...)
If my database was online, with good credentials
Succeed with command prompt :
Replaced OutPutDir by o
Removed verbose
Removed single quotes
Command :
dotnet ef dbcontext scaffold "MY_CONNECTION_STRING" Microsoft.EntityFrameworkCore.SqlServer -o MY_ABSOLUTE_PATH

ConfigurationType error when using Entity Framework migrate.exe with multiple migration configurations

In my solution, I have a Data project that contains multiple Entity Framework 6.1.3 migration configuration classes. My goal is to run Entity Framework migration steps - for one of them, against an existing database - from TeamCity (or, to simplify, from a command line).
The migration configuration class I am using is the following:
namespace MyProject.Data
{
public partial class MyCustomMigrationConfiguration :
DbMigrationsConfiguration<MyCustomContext>
{
public MyCustomMigrationConfiguration()
{
AutomaticMigrationsEnabled = false;
AutomaticMigrationDataLossAllowed = true;
MigrationsDirectory = #"Migrations\MyCustomContext\MigrationSteps";
}
}
}
I can successfully run the following command from Package Manager Console in Visual Studio:
Update-Database -Verbose -StartUpProject Web -ConnectionString '-my
connection string here-' -ConfigurationTypeName
MyCustomMigrationConfiguration -ConnectionProviderName
'System.Data.SqlClient'
I want to do the same thing from a command line, so I run this:
migrate.exe MyProject.Data.dll "MyCustomMigrationConfiguration"
/startUpConfigurationFile=MyProject.Web.dll.config
/connectionString="-my connection string here-;"
/connectionProviderName="System.Data.SqlClient" /verbose
However, I get the following error:
ERROR: The migrations configuration type
MyCustomMigrationConfiguration was not be found in the assembly
‘MyProject.Data'.
Any suggestions on how to fix this, please?
You can specify the directory where are all the dependencies (assemblies) needed to run your code. You can do that by using the /startUpDirectory option, as explained here:
Specify working directory
Migrate.exe MyApp.exe /startupConfigurationFile=”MyApp.exe.config” /startupDirectory=”c:\MyApp”
If you assembly has dependencies or reads files relative to the working directory then you will need to set startupDirectory.
Found the solution (I ended up downloading the Entity Framework source code from http://entityframework.codeplex.com/ and debugging the migrate console application).
Apparently, all the dependencies of MyProject.Data.dll need to be copied in the same folder with it and migrate.exe, otherwise the Entity Framework migrate.exe tool will throw the misleading error message above.
Entity Framework could really use better error handling and a clearer error message in this case.
As a reference to Entity Framework devs: the following code in TypeFinder.cs was returning a null type because the dependencies of MyProject.Data.dll were not copied in the folder of migrate.exe:
type = _assembly.GetType(typeName, false);

EF Migrations migrate.exe generate script

I'm playing around with Entity framework and continuous builds. So far i'm able to run a migration or series of migrations without any problem by using migrate.exe and the appropriate arguments.
However, i've hit trouble when trying to get migrate.exe to kick out a script, rather than perform the migration, in the same way as I could get by running
update-database -TargetMigration TestMigration -script
from within Package Manager Console in Visual Studio.
Is there currently a way to do this?
Thanks.
Since the 10/22/2017 you can do it thanks to this PR:
https://github.com/aspnet/EntityFramework6/commit/02ec6b8c9279f93f80eeed1234e5ce0acfce5f31
Here the Entity Framework 6.2 release notes that implements this functionality (see 'Migrate.exe should support -script option' section):
https://blogs.msdn.microsoft.com/dotnet/2017/10/26/entity-framework-6-2-runtime-released/
Follow those steps:
Copy the file migrate.exe from the '\packages\EntityFramework.6.2.0\tools' to the target 'bin' folder (for example on the production server) after that you deployed the new assembly that contains the new migrations
Open the command line in the folder and launch this command:
migrate.exe yourMigrationAssembly.dll
/startupConfigurationFile=”..\web.config”
/scriptFile="migrationOutput.sql"
It will generate the the file "migrationOutput.sql" that contains the SQL you have to execute on your target environment DB based on the migrations that are not yet applied on it.
It is currently not supported. Please add your vote to the issue: Migrations: -Script for Migrate.exe
I encountered the same problem and indeed the option is available in the package manager console in Visual Studio. So I opened up the powershell script and the entity framework dll and built a small executable so you can generate the scripts from command line.The source code is available as-is and without any warranty here;
EF6
EF5
You can write a simple c# console application or use something like Linqpad to generate the script using the Entity Framework Infrastructure objects. You will just need to load the DLL with your DbMigrationsConfiguration class and instantiate it. Here is the code similar to what is working for me:
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Infrastructure;
const string ScriptFile = "Migration.sql";
const string ConnectionString = #"Server=.\SqlExpress;Database=...;Trusted_Connection=True;";
const bool AutomaticMigrationDataLossAllowed = false;
var targetDb = new DbConnectionInfo(ConnectionString, "System.Data.SqlClient");
var config = new MyDbMigrationsConfiguration
{
AutomaticMigrationDataLossAllowed = AutomaticMigrationDataLossAllowed,
TargetDatabase = targetDb,
};
var migrator = new DbMigrator(config);
var scripter = new MigratorScriptingDecorator(migrator);
var script = scripter.ScriptUpdate(null, null);
File.WriteAllText(ScriptFile, script);
Console.WriteLine("Migration Script Generated: " + ScriptFile);