I'm sure I'll figure out what is wrong after posting this but here goes.
I'm trying to get an EF Migration bundle going in my devops pipeline so I can deploy updates/changes to my db with my CD pipeline.
Below is my yaml file. I've omitted variables as some are sensitive
stages:
- stage: Build
displayName: Build stage
jobs:
- job: Build
displayName: Build
pool:
vmImage: $(vmImageName)
steps:
- task: UseDotNet@2
inputs:
packageType: 'sdk'
version: '8.x'
- task: DotNetCoreCLI@2
displayName: 'Install Dotnet EF Tool'
inputs:
command: custom
custom: "tool"
arguments: "install --global dotnet-ef"
- task: DotNetCoreCLI@2
displayName: EFBundle
inputs:
command: 'custom'
custom: 'ef '
arguments: 'migrations bundle --configuration Release --self-contained -r win-x64 -p "$(System.DefaultWorkingDirectory)\EntityFramework\EntityFramework.csproj" -o $(Build.ArtifactStagingDirectory)\SQL\bundle.exe --force'
- task: PublishBuildArtifacts@1
displayName: 'PublishArtifacts - SQL Bundle'
inputs:
pathToPublish: '$(Build.ArtifactStagingDirectory)/SQL'
artifactName: 'SQL'
- task: DotNetCoreCLI@2
displayName: Restore
inputs:
command: 'restore'
projects: |
$(workingDirectory)\*.csproj
- task: DotNetCoreCLI@2
displayName: Build
inputs:
command: 'build'
projects: |
$(workingDirectory)\*.csproj
arguments: '--output $(System.DefaultWorkingDirectory)\publish_output --configuration Release'
- task: ArchiveFiles@2
displayName: 'Archive files'
inputs:
rootFolderOrFile: '$(System.DefaultWorkingDirectory)\publish_output'
includeRootFolder: false
archiveType: zip
archiveFile: $(Build.ArtifactStagingDirectory)\$(Build.BuildId).zip
replaceExistingArchive: true
- publish: $(Build.ArtifactStagingDirectory)\$(Build.BuildId).zip
artifact: drop
- stage: DeployToDevelopment
displayName: Deploy to Development Slot
dependsOn: Build
condition: succeeded()
jobs:
- deployment: DeployDevelopment
displayName: Deploy to Development Environment
environment: 'development'
pool:
vmImage: $(vmImageName)
strategy:
runOnce:
deploy:
steps:
- task: AzureCLI@2
displayName: 'Azure SQL Schema Deployment'
env:
MonoConnectionString: $(devConnectionString)
inputs:
scriptType: 'pscore'
scriptLocation: 'inlineScript'
azureSubscription: '$(azureSubscription)'
inlineScript: |
cd $(Pipeline.Workspace)/SQL
./bundle.exe --connection "$(devConnectionString)" --verbose
- task: AzureFunctionApp@1
displayName: 'Deploy to Development App'
inputs:
azureSubscription: '$(azureSubscription)'
appType: 'functionApp'
appName: $(devFunctionAppName)
package: '$(Pipeline.Workspace)\drop\$(Build.BuildId).zip'
- stage: DeployToProduction
displayName: Deploy to Production Slot
dependsOn: DeployToDevelopment
condition: succeeded()
jobs:
- deployment: DeployProduction
displayName: Deploy to Production Slot
environment: 'production' # Make sure this environment has manual approvals configured in Azure DevOps
pool:
vmImage: $(vmImageName)
strategy:
runOnce:
deploy:
steps:
- task: AzureCLI@2
displayName: 'Run EF Migrations Bundle for Production'
env:
MonoConnectionString: $(connectionString)
inputs:
scriptType: 'pscore'
scriptLocation: 'inlineScript'
azureSubscription: '$(azureSubscription)'
inlineScript: |
cd $(Pipeline.Workspace)/SQL
./bundle.exe AddedEmailToInvitationTable --verbose
- task: AzureFunctionApp@1
displayName: 'Deploy to Production Slot'
inputs:
azureSubscription: '$(azureSubscription)'
appType: 'functionApp'
appName: $(functionAppName)
package: '$(Pipeline.Workspace)\drop\$(Build.BuildId).zip'
As you can see I'm running the typical dotnet ef migrations bundle
command with the --force
flag so it overwrites any bundle already present (which there shouldn't be anyway).
My EF migrations are contained inside a project called EntityFramework
. Here is a screen shot of that in my IDE.
As you can see, I've already applied migrations and have deployed them to my dev db via my IDE by simply calling database update
(that works as expected).
The problem I face is once my production deploy pipeline runs, I always get a message saying the database is already up to date. I thought at first perhaps my prod stage was looking at my dev db, but that's not the case as you can clearly see in this output that it created an __EFMigrations table
Executed DbCommand (36ms) [Parameters=[], CommandType='Text', CommandTimeout='1800']
SELECT OBJECT_ID(N'[__EFMigrationsHistory]');
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (21ms) [Parameters=[], CommandType='Text', CommandTimeout='1800']
SELECT 1
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (27ms) [Parameters=[], CommandType='Text', CommandTimeout='1800']
CREATE TABLE [__EFMigrationsHistory] (
[MigrationId] nvarchar(150) NOT NULL,
[ProductVersion] nvarchar(32) NOT NULL,
CONSTRAINT [PK___EFMigrationsHistory] PRIMARY KEY ([MigrationId])
);
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (20ms) [Parameters=[], CommandType='Text', CommandTimeout='1800']
SELECT 1
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (22ms) [Parameters=[], CommandType='Text', CommandTimeout='1800']
SELECT OBJECT_ID(N'[__EFMigrationsHistory]');
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (29ms) [Parameters=[], CommandType='Text', CommandTimeout='1800']
SELECT [MigrationId], [ProductVersion]
FROM [__EFMigrationsHistory]
ORDER BY [MigrationId];
info: Microsoft.EntityFrameworkCore.Migrations[20405]
No migrations were applied. The database is already up to date.
So to troubleshoot the issue I added a specific migration to my ./bundle.exe
command. If you look at my yaml above you will see it called AddedEmailToInvitationTable
. When I run that I get an error saying that there is no migration with that name; and hence I've come to the conclusion that for some reason, my dotnet ef migrations bundle
command is some how not seeing my actual migrations`
System.InvalidOperationException: The migration 'AddedEmailToInvitationTable' was not found.
How can I make sure the bundle command explicitly incorporates my migrations folder?OR perhaps, is there anything obvious I am doing wrong?
Yup, as I mentioned in my question, I would figure out the answer once I posted. It's a strange one to say the least.
Adding .MigrationsAssembly("EntityFramework")
to my AddDbContext
call seemed to magically tell the EF Migrations where to find my migrations even though the migration assembly is the same exact assembly I was running the commands on hehe.
Here is the total code
builder.Services.AddDbContext<MonoContext>(a =>
a.UseSqlServer(dbConn, opts =>
opts.CommandTimeout((int)TimeSpan.FromMinutes(30).TotalSeconds)
.MigrationsAssembly("EntityFramework"))
.EnableDetailedErrors()
.EnableSensitiveDataLogging());
I figured it out by trying to run dotnet ef migrations list
locally on my project. No matter what I did it would not list any migrations. So I then google searched "no migrations found ef core" and found other people who had a similar issue outside of the context of ef bundles.