# 数据库迁移脚本 # 导入必要的模块 using namespace System.Management.Automation.Host # 加入环境变量FROM_MIGRATION,使其在Program.cs文件中可以进行判断 $env:FROM_MIGRATION = "true" # 定义项目路径 $projectPath = Resolve-Path (Join-Path $PSScriptRoot "..") # 定义函数来动态查找所有可用的DbContext function Get-AvailableDbContexts { $migrationsPath = Join-Path $projectPath "migrations" $dbContexts = @{} $counter = 1 # 查找所有包含EntityFrameworkCore的目录 $efCoreDirectories = Get-ChildItem -Path $migrationsPath -Directory | Where-Object { $_.Name -like "*EntityFrameworkCore*" } foreach ($dir in $efCoreDirectories) { # 优先查找 DbContextFactory 文件 $factoryFiles = Get-ChildItem -Path $dir.FullName -Filter "*DbContextFactory.cs" -Recurse -File # 如果找到了 Factory 文件 $foundFactory = $false foreach ($factoryFile in $factoryFiles) { $factoryContent = Get-Content $factoryFile.FullName -Raw # 查找 Factory 类名和对应的 DbContext 类 if ($factoryContent -match 'class\s+(\w+Factory)\s*:\s*IDesignTimeDbContextFactory<(\w+)>') { $factoryName = $matches[1] $contextName = $matches[2] # 如果找到了上下文和工厂,添加到列表中 $dbContexts["$counter"] = @{ Name = $dir.Name Context = $contextName Factory = $factoryName } $counter++ $foundFactory = $true } } # 只有当没有找到 Factory 时,才查找 DbContext 文件作为备选 if (-not $foundFactory) { $dbContextFiles = Get-ChildItem -Path $dir.FullName -Filter "*DbContext.cs" -Recurse -File foreach ($contextFile in $dbContextFiles) { $contextContent = Get-Content $contextFile.FullName -Raw if ($contextContent -match 'class\s+(\w+DbContext)') { $contextName = $matches[1] # 添加到列表中,但没有对应的 Factory $dbContexts["$counter"] = @{ Name = $dir.Name Context = $contextName Factory = $null } $counter++ } } } } # 如果没有找到任何上下文,使用默认的 if ($dbContexts.Count -eq 0) { $dbContexts["1"] = @{ Name = "PackageName.CompanyName.ProjectName.AIO.EntityFrameworkCore.DatabaseManagementName" Context = "SingleMigrationsDbContext" Factory = "SingleMigrationsDbContextFactory" } } return $dbContexts } # 获取可用的DbContext $dbContexts = Get-AvailableDbContexts # 显示DbContext选择菜单 function Show-DbContextMenu { $host.UI.RawUI.BackgroundColor = "Black" $host.UI.RawUI.ForegroundColor = "White" Clear-Host Write-Host "========================================" -ForegroundColor Cyan Write-Host " 数据库迁移上下文选择" -ForegroundColor Yellow Write-Host "========================================" -ForegroundColor Cyan Write-Host "" Write-Host "请选择要迁移的数据库上下文:" -ForegroundColor Green foreach ($key in $dbContexts.Keys) { $context = $dbContexts[$key] Write-Host "[$key] " -NoNewline -ForegroundColor Magenta Write-Host "$($context.Name)" -ForegroundColor White } Write-Host "" } # 选择DbContext function Select-DbContext { Show-DbContextMenu while ($true) { $choice = Read-Host "请输入数字选择" if ($dbContexts.ContainsKey($choice)) { return $dbContexts[$choice] } Write-Host "无效的选择,请重新输入。" -ForegroundColor Red } } # 获取迁移名称 function Get-MigrationName { $defaultName = "AddNewMigration_" + (Get-Date -Format "yyyyMMdd_HHmmss") $migrationName = Read-Host "请输入迁移名称 (留空将使用默认名称: $defaultName)" return ($migrationName ? $migrationName : $defaultName) } # 执行数据库迁移 function Invoke-DatabaseMigration($dbContext, $migrationName) { Write-Host "========================================" -ForegroundColor Cyan Write-Host "正在执行数据库迁移..." -ForegroundColor Green Write-Host "上下文: " -NoNewline -ForegroundColor Yellow Write-Host "$($dbContext.Name)" -ForegroundColor White Write-Host "迁移名称: " -NoNewline -ForegroundColor Yellow Write-Host "$migrationName" -ForegroundColor White Write-Host "项目路径: " -NoNewline -ForegroundColor Yellow Write-Host "$projectPath" -ForegroundColor White Write-Host "========================================" -ForegroundColor Cyan # 切换到项目目录并执行迁移 Push-Location $projectPath try { dotnet ef migrations add $migrationName --project "migrations/$($dbContext.Name)" --context "$($dbContext.Context)" } finally { Pop-Location } } # 获取所有迁移文件 function Get-AllMigrations($dbContext) { Push-Location $projectPath try { $migrations = @(dotnet ef migrations list --project "migrations/$($dbContext.Name)" --context "$($dbContext.Context)") return $migrations | Where-Object { $_ -match '\S' } # 过滤空行 } finally { Pop-Location } } # 选择起始迁移 function Select-FromMigration($dbContext) { $migrations = Get-AllMigrations -dbContext $dbContext Write-Host "========================================" -ForegroundColor Cyan Write-Host "可用的迁移文件:" -ForegroundColor Yellow Write-Host "========================================" -ForegroundColor Cyan for ($i = 0; $i -lt $migrations.Count; $i++) { Write-Host "[$i] " -NoNewline -ForegroundColor Magenta Write-Host "$($migrations[$i])" -ForegroundColor White } Write-Host "[A] " -NoNewline -ForegroundColor Magenta Write-Host "生成所有迁移的SQL脚本" -ForegroundColor White Write-Host "[L] " -NoNewline -ForegroundColor Magenta Write-Host "仅生成最新迁移的SQL脚本" -ForegroundColor White while ($true) { $choice = Read-Host "请选择起始迁移文件" if ($choice -eq "A" -or $choice -eq "a") { return $null } if ($choice -eq "L" -or $choice -eq "l") { if ($migrations.Count -gt 1) { return $migrations[$migrations.Count - 2] } return $null } if ([int]::TryParse($choice, [ref]$null)) { $index = [int]$choice if ($index -ge 0 -and $index -lt $migrations.Count) { return $migrations[$index] } } Write-Host "无效的选择,请重新输入。" -ForegroundColor Red } } # 生成SQL脚本 function Export-SqlScript($dbContext, $migrationName) { $choice = Read-Host "是否生成SQL迁移脚本?(Y/N)" if ($choice -eq "Y" -or $choice -eq "y") { $sqlFileName = (Get-Date -Format "yyyyMMddHHmm") + ".sql" $initSqlPath = Join-Path $projectPath "InitSql" $contextSqlPath = Join-Path $initSqlPath $dbContext.Name # 确保InitSql和上下文特定目录存在 if (-not (Test-Path $initSqlPath)) { New-Item -ItemType Directory -Path $initSqlPath | Out-Null } if (-not (Test-Path $contextSqlPath)) { New-Item -ItemType Directory -Path $contextSqlPath | Out-Null } $sqlFilePath = Join-Path $contextSqlPath $sqlFileName # 选择起始迁移 $fromMigration = Select-FromMigration -dbContext $dbContext Write-Host "========================================" -ForegroundColor Cyan Write-Host "正在生成SQL脚本..." -ForegroundColor Green Write-Host "输出路径: " -NoNewline -ForegroundColor Yellow Write-Host "$sqlFilePath" -ForegroundColor White if ($fromMigration) { Write-Host "起始迁移: " -NoNewline -ForegroundColor Yellow Write-Host "$fromMigration" -ForegroundColor White } Write-Host "========================================" -ForegroundColor Cyan # 切换到项目目录并生成SQL脚本 Push-Location $projectPath try { if ($fromMigration) { dotnet ef migrations script $fromMigration --project "migrations/$($dbContext.Name)" --context "$($dbContext.Context)" --output $sqlFilePath } else { dotnet ef migrations script --project "migrations/$($dbContext.Name)" --context "$($dbContext.Context)" --output $sqlFilePath } } finally { Pop-Location } Write-Host "SQL脚本已生成: " -NoNewline -ForegroundColor Green Write-Host "$sqlFilePath" -ForegroundColor White } } # 主执行流程 try { $dbContext = Select-DbContext $migrationName = Get-MigrationName Invoke-DatabaseMigration -dbContext $dbContext -migrationName $migrationName # 生成SQL脚本 Export-SqlScript -dbContext $dbContext -migrationName $migrationName Write-Host "迁移完成!" -ForegroundColor Green } catch { Write-Host "迁移过程中发生错误:" -ForegroundColor Red Write-Host $_.Exception.Message -ForegroundColor Red } finally { Write-Host "`n按任意键退出..." $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") }