feat: 重构数据库迁移架构,支持多数据库提供程序 (SQLite/SQLServer/PostgreSQL/MySQL)
- 将迁移文件按数据库类型分目录存放 (Migrations/SQLite, MySQL, PostgreSQL, SqlServer) - 新增各数据库提供程序的 DesignTimeDbContextFactory,支持 --provider 参数切换 - 新增 ProviderAppDataContexts,定义各数据库对应的 AppDataContext 子类 - DatabaseExtensions 增加 AddProviderAppDataContext 方法,按配置自动注册对应 DbContext - 修正 MySQL 提供程序调用方式 (UseMySql -> UseMySQL) - UserEntity 模型增加新字段 - 更新 add-migration.ps1
This commit is contained in:
+61
-34
@@ -1,6 +1,7 @@
|
||||
param(
|
||||
[string]$Name,
|
||||
[string]$Context = "AppDataContext",
|
||||
[ValidateSet("SQLite", "SqlServer", "PostgreSQL", "MySQL", "All")]
|
||||
[string]$Provider = "All",
|
||||
[string]$Project = "Avalonia-EFCore/Avalonia-EFCore.csproj",
|
||||
[string]$StartupProject = "Avalonia-API/Avalonia-API.csproj",
|
||||
[string]$OutputDir = "Migrations"
|
||||
@@ -21,45 +22,71 @@ if ($LASTEXITCODE -ne 0) {
|
||||
throw "dotnet tool restore failed."
|
||||
}
|
||||
|
||||
Write-Host "Generating migration '$Name'..."
|
||||
dotnet tool run dotnet-ef migrations add $Name `
|
||||
--project $Project `
|
||||
--startup-project $StartupProject `
|
||||
--context $Context `
|
||||
--output-dir $OutputDir
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "dotnet ef migrations add failed."
|
||||
function Get-ContextName([string]$providerName) {
|
||||
switch ($providerName) {
|
||||
"SQLite" { return "SqliteAppDataContext" }
|
||||
"SqlServer" { return "SqlServerAppDataContext" }
|
||||
"PostgreSQL" { return "PostgreSqlAppDataContext" }
|
||||
"MySQL" { return "MySqlAppDataContext" }
|
||||
default { throw "Unsupported provider '$providerName'." }
|
||||
}
|
||||
}
|
||||
|
||||
$migrationDir = Join-Path (Split-Path $Project -Parent) $OutputDir
|
||||
$migrationFile = Get-ChildItem $migrationDir -Filter "*_$Name.cs" |
|
||||
Where-Object { $_.Name -notlike "*.Designer.cs" } |
|
||||
Sort-Object LastWriteTime -Descending |
|
||||
Select-Object -First 1
|
||||
function Add-ProviderMigration([string]$providerName) {
|
||||
$context = Get-ContextName $providerName
|
||||
$providerOutputDir = Join-Path $OutputDir $providerName
|
||||
|
||||
if ($null -eq $migrationFile) {
|
||||
throw "Migration file was not found for '$Name'."
|
||||
}
|
||||
|
||||
$content = Get-Content $migrationFile.FullName -Raw
|
||||
$upMatch = [regex]::Match($content, "protected override void Up\(MigrationBuilder migrationBuilder\)\s*\{(?<body>.*?)\n\s*\}", "Singleline")
|
||||
$downMatch = [regex]::Match($content, "protected override void Down\(MigrationBuilder migrationBuilder\)\s*\{(?<body>.*?)\n\s*\}", "Singleline")
|
||||
|
||||
$upBody = if ($upMatch.Success) { $upMatch.Groups["body"].Value.Trim() } else { "" }
|
||||
$downBody = if ($downMatch.Success) { $downMatch.Groups["body"].Value.Trim() } else { "" }
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($upBody) -and [string]::IsNullOrWhiteSpace($downBody)) {
|
||||
Write-Host "No model changes were detected. Removing empty migration '$Name'..."
|
||||
dotnet tool run dotnet-ef migrations remove --force `
|
||||
Write-Host "Generating migration '$Name' for $providerName..."
|
||||
dotnet tool run dotnet-ef migrations add $Name `
|
||||
--project $Project `
|
||||
--startup-project $StartupProject `
|
||||
--context $Context
|
||||
--context $context `
|
||||
--output-dir $providerOutputDir
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "dotnet ef migrations remove failed."
|
||||
throw "dotnet ef migrations add failed for $providerName."
|
||||
}
|
||||
exit 0
|
||||
|
||||
$migrationDir = Join-Path (Split-Path $Project -Parent) $providerOutputDir
|
||||
$migrationFile = Get-ChildItem $migrationDir -Filter "*_$Name.cs" |
|
||||
Where-Object { $_.Name -notlike "*.Designer.cs" } |
|
||||
Sort-Object LastWriteTime -Descending |
|
||||
Select-Object -First 1
|
||||
|
||||
if ($null -eq $migrationFile) {
|
||||
throw "Migration file was not found for '$Name' ($providerName)."
|
||||
}
|
||||
|
||||
$content = Get-Content $migrationFile.FullName -Raw
|
||||
$upMatch = [regex]::Match($content, "protected override void Up\(MigrationBuilder migrationBuilder\)\s*\{(?<body>.*?)\n\s*\}", "Singleline")
|
||||
$downMatch = [regex]::Match($content, "protected override void Down\(MigrationBuilder migrationBuilder\)\s*\{(?<body>.*?)\n\s*\}", "Singleline")
|
||||
|
||||
$upBody = if ($upMatch.Success) { $upMatch.Groups["body"].Value.Trim() } else { "" }
|
||||
$downBody = if ($downMatch.Success) { $downMatch.Groups["body"].Value.Trim() } else { "" }
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($upBody) -and [string]::IsNullOrWhiteSpace($downBody)) {
|
||||
Write-Host "No model changes were detected for $providerName. Removing empty migration '$Name'..."
|
||||
dotnet tool run dotnet-ef migrations remove --force `
|
||||
--project $Project `
|
||||
--startup-project $StartupProject `
|
||||
--context $context
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "dotnet ef migrations remove failed for $providerName."
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
Write-Host "Migration generated for ${providerName}:"
|
||||
Write-Host " $($migrationFile.FullName)"
|
||||
}
|
||||
|
||||
Write-Host "Migration generated:"
|
||||
Write-Host " $($migrationFile.FullName)"
|
||||
Write-Host "Review the migration, then start the app. Startup will automatically apply pending migrations."
|
||||
$providers = if ($Provider -eq "All") {
|
||||
@("SQLite", "SqlServer", "PostgreSQL", "MySQL")
|
||||
} else {
|
||||
@($Provider)
|
||||
}
|
||||
|
||||
foreach ($providerName in $providers) {
|
||||
Add-ProviderMigration $providerName
|
||||
}
|
||||
|
||||
Write-Host "Review the migration files, then start the app. Startup will apply the migration set matching DatabaseConfiguration.Provider."
|
||||
|
||||
Reference in New Issue
Block a user