Entity Framework Migration Azure DevOps Release Pipeline - entity-framework

I'm trying to run migration on Azure DevOps Release Pipeline. Because I want to run my DB scripts automatically on every release. My release pipeline does not have source code, I just have compiled DLLs.
When I execute this command on my local machine, it runs successfully. How can I convert this command so I can use it with DLLs.
dotnet ef database update --project MyEntityFrameworkProject --context MyDbContext --startup-project MyStartupProject

Another approach is to generate migration script (a regular sql script) during build pipeline and make this script a part of your artifact. To do so run following command:
dotnet ef migrations script --output $(build.artifactstagingdirectory)\sql\migrations.sql -i
Note -i flag which makes this script runnable multiple times on the same database
Once you have this script as a part of your artifact you can run it on database in your release pipeline by using Azure SQL Database Deployment built in task.
Check this link for more info
EDIT: As #PartickBorkowicz pointed out there are some issues related to the fact that database is not available in a regular way from Build/Release Agent perspective. Here are some additional tips how to live without a database and connection string stored anywhere in your code.
1. Build pipeline
If you do nothing, an Build Agent will require database connection in order to run dotnet ef migrations script script. But there's one trick you can do which will allow you to work without database and connection string: IDesignTimeDbContextFactory
It's enough that you create class like this:
public class YourDesignTimeContextFactory : IDesignTimeDbContextFactory<YourDbContext>
{
public YourDbContext CreateDbContext(string[] args)
{
var databaseConnectionString = "Data Source=(LocalDB)\\MSSQLLocalDB;Initial Catalog=LocalDB;Integrated Security=True;Pooling=False";
var builder = new DbContextOptionsBuilder<YourDbContext>();
builder.UseSqlServer(databaseConnectionString);
return new YourDbContext(builder.Options);
}
}
Once it is present in your project (you don't need to register it anyhow) your Build Agent will be able to generate sql script with migrations logic without access to actual database
2. Release pipeline
Now, you're having sql script generated and being part of artifact from a build pipeline. Now, release pipeline is the time when you want this script to be run on actual database - you'll need a connection string to this database somehow. To do so in secure manner you should not store it anywhere in the code. A good way to do it is to keep password in Azure Key Vault. There's built in task in Azure Release pipelines called Azure Key Vault. This will fetch your secrets which you can use in next step: Azure SQL Database Deployment. You just need to setup options:
AuthenticationType: Connection String
ConnectionString: `$(SqlServer--ConnectionString)` - this value depends on your secret name in Key Vault
Deploy type: SQL Script File
SQL Script: $(System.DefaultWorkingDirectory)/YourProject/drop/migrations/script.sql - this depends how you setup your artifact in build pipeline.
This way you're able to generate migrations without access to database and run migrations sql without storing your connection string anywhere in the code.

If you don't want to include your source code with the artifacts you can use the following script:
set rootDir=$(System.DefaultWorkingDirectory)\WebApp\drop\WebApp.Web
set efPath=C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.entityframeworkcore.tools\2.1.1\tools\netcoreapp2.0\any\ef.dll
dotnet exec --depsfile "%rootDir%\WebApp.deps.json" --additionalprobingpath %USERPROFILE%\.nuget\packages --additionalprobingpath "C:\Program Files\dotnet\sdk\NuGetFallbackFolder" --runtimeconfig "%rootDir%\WebApp.runtimeconfig.json" "%efpath%" database update --verbose --prefix-output --assembly "%rootDir%\AssemblyContainingDbContext.dll" --startup-assembly "%rootDir%\AssemblyContainingStartup.dll" --working-dir "%rootDir%"
It turns out you can get away with the undocumented dotnet exec command like the following example (assuming the web application is called WebApp):
Note that the Working Directory (hidden under Advanced) of this run command line task must be set to where the artifacts are (rootDir above).
Another option is to install Build & Release Tools extension and use the "Deploy Entity Framework Core Migrations from a DLL" task.
You can read more info here, here and here.

Related

postgres schema name passing using yuniql

I'm trying to update PostgreSQL schema name in yuniql with azure devops release pipeline .
When i'm executing it is connecting to default schema.
kindly suggest if any one knows.
I tried with setx command as well.
is there any possible for alternate way using pipelines only.

How do you run many SQL commands against an Azure SQL database using an Azure Automation powershell runbook

I'm using Azure Automation to move an Azure SQL database from one resource to another(from Prod to Dev for example). After the database is copied, I would then like to run SQL script that adds some users and permissions. This would mean I need to run a handful of commands like "Create user..." and "alter role....". Most examples I've found use powershell to execute a single SQL command, but using that code to run many commands seems like it would result in an excessively long powershell script. In the on-prem world, I probably would have .sql file that gets executed. Any suggestions on how to achieve this easily using powershell in Azure Automation. Thanks!

Dacpac publish how to ignore create database statement?

Due to shared database, we don't have admin privs. Only we have schema id.
In dacpac build or sqlpackage.exe publish is there anyway to ignore the Create database statement ?
2020-03-23T21:48:54.5875811Z ##[error]*** Could not deploy package.
2020-03-23T21:48:54.5930784Z ##[error]Error SQL72014: .Net SqlClient Data Provider: Msg 262, Level 14, State 1, Line 1 CREATE DATABASE permission denied in database 'master'.
Error SQL72045: Script execution error. The executed script:
CREATE DATABASE [$(Datab
2020-03-23T21:48:54.6200608Z ##[error]aseName)] COLLATE SQL_Latin1_General_CP1_CI_AS
i tried with below option in sqlpackage.exe and it's not working
/p:CreateNewDatabase=False /p:ExcludeObjectTypes=Users;Logins;RoleMembership;Permissions;Credentials;DatabaseScopedCredentials
is it possible to hack the dacpac sql script comment the create database and from next version it should able to skip because of incremental load? Appreciate your idea.
For Azure sql datawarehouse is there any alternative to DACPAC deployment ?
You can use sqlpackage.exe to generate update scripts (/a:Script) between your dacpac and target database. Then you can remove unneeded instruction. Here is example to create pipeline: Azure Pipelines - Generating DB Script with SqlPackage.exe

I get this error on my production server, but the application works locally just fine

Migrations is enabled for context 'ApplicationDbContext' but the
database does not exist or contains no mapped tables. Use Migrations
to create the database and its tables, for example by running the
'Update-Database' command from the Package Manager Console.
Can anyone explaing why?
If your dev system is working and prod is not, you can generate a script to bring them back in sync:
update-database -Script –SourceMigration $InitialDatabase
This will create an idempotent script that will test what has been applied and what hasn't. Now use SQL Server Management Studio to apply that script.
https://msdn.microsoft.com/en-us/data/jj591621.aspx?f=255&MSPPError=-2147217396#idempotent

Script EF migration seed from Configuration class

I have EF migrations working nicely, but I also want to generate the sql script for the seed data from my DbMigrationsConfiguration class.
The seed data runs ok when I do Update-Database, but when I do UpdateDatabase -Script I do not get the sql for the seed inserts. I tried -Verbose on a normal Update-Database but I do not see the seed statements output there either.
Is this possible?
No it is not possible. Configuration class is not part of migration itself - it is infrastructure executing the migration. You have single configuration class for all your migrations and its Seed method is executed after every migration run - you can even use context for seeding data and because of that this method is executed after the migration is completed = it cannot be part of migration. Only content of the migration class is scripted.
Whether you are using EF or EF Core, a solution/workaround is to have SSMS generate the seed script for you:
Start with a clean database generated by your DB initializer and seed method. Make sure the data you want scripted is in there.
Using SSMS, right-click the database, go to Tasks > "Generate Scripts...", and follow the wizard. Under Advanced options, be sure to select "Data only" for "Types of data to script".
From the generated script, copy required seed statements over to your target script.
I know it's bit of an old thread but, here is an answer that could help someone else looking for an answer.
You can use the Migrate.exe supplied by Entity Framework. This will allow you to run the Seed method on the database context.
If you need to run a specific Seed method you can place that in a separate migration config file like this:
Enable-Migrations -MigrationsDirectory "Migrations\ContextA" -ContextTypeName MyProject.Models.ContextA
Command:
Migrate.exe MyAssembly CustomConfig /startupConfigurationFile=”..\web.config”
Look for it in the NuGet packages directory: "..\packages\EntityFramework.6.1.3\tools"
You can specify migration configuration as an argument to it. The CustomConfig should contain your code based Seed method. So, This way you do not require SQL scripts to be generated from the migration.
More info here:
http://www.eidias.com/blog/2014/10/13/initialcreate-migration-and-why-is-it-important
http://www.gitshah.com/2014/06/how-to-run-entity-framework-migrations.html
Using this solution, you do not need to generate an SQL script and can run multiple Seeds for different environments.