Browse Source

Merge pull request #7889 from abpframework/volo/issue/5635

Cli: support for Separate tenant schema
pull/7907/head
Halil İbrahim Kalkan 6 years ago
committed by GitHub
parent
commit
420449c455
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs
  2. 76
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CreateMigrationAndRunMigratorCommand.cs
  3. 9
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/DatabaseManagementSystemChangeStep.cs
  4. 1
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/RemoveCmsKitStep.cs
  5. 15
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs
  6. 59
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/EfCoreMigrationManager.cs
  7. 13
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs

7
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs

@ -59,7 +59,6 @@ namespace Volo.Abp.Cli.Commands
await SolutionModuleAdder.AddAsync(
solutionFile,
commandLineArgs.Target,
commandLineArgs.Options.GetOrNull(Options.StartupProject.Short, Options.StartupProject.Long),
version,
skipDbMigrations,
withSourceCode,
@ -167,12 +166,6 @@ namespace Volo.Abp.Cli.Commands
public const string Skip = "skip-db-migrations";
}
public static class StartupProject
{
public const string Short = "sp";
public const string Long = "startup-project";
}
public static class SourceCode
{
public const string Long = "with-source-code";

76
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CreateMigrationAndRunMigratorCommand.cs

@ -26,7 +26,9 @@ namespace Volo.Abp.Cli.Commands
throw new CliUsageException("DbMigrations folder path is missing!");
}
var dbMigratorProjectPath = GetDbMigratorProjectPath(commandLineArgs.Target);
var dbMigrationsFolder = commandLineArgs.Target;
var dbMigratorProjectPath = GetDbMigratorProjectPath(dbMigrationsFolder);
if (dbMigratorProjectPath == null)
{
throw new Exception("DbMigrator is not found!");
@ -37,13 +39,17 @@ namespace Volo.Abp.Cli.Commands
InstallDotnetEfTool();
}
var addMigrationCmd = $"cd \"{commandLineArgs.Target}\" && " +
$"dotnet ef migrations add Initial -s \"{dbMigratorProjectPath}\"";
var tenantDbContextName = FindTenantDbContextName(dbMigrationsFolder);
var dbContextName = tenantDbContextName != null ?
FindDbContextName(dbMigrationsFolder)
: null;
var migrationOutput = AddMigrationAndGetOutput(dbMigrationsFolder, dbContextName, "Migrations");
var tenantMigrationOutput = tenantDbContextName != null ?
AddMigrationAndGetOutput(dbMigrationsFolder, tenantDbContextName, "TenantMigrations")
: null;
var output = CmdHelper.RunCmdAndGetOutput(addMigrationCmd);
if (output.Contains("Done.") &&
output.Contains("To undo this action") &&
output.Contains("ef migrations remove"))
if (CheckMigrationOutput(migrationOutput) && CheckMigrationOutput(tenantMigrationOutput))
{
// Migration added successfully
CmdHelper.RunCmd("cd \"" + Path.GetDirectoryName(dbMigratorProjectPath) + "\" && dotnet run");
@ -51,22 +57,70 @@ namespace Volo.Abp.Cli.Commands
}
else
{
var exceptionMsg = "Migrations failed! The following command didn't run successfully:" +
var exceptionMsg = "Migrations failed! A migration command didn't run successfully:" +
Environment.NewLine +
addMigrationCmd +
Environment.NewLine + output;
Environment.NewLine + migrationOutput +
Environment.NewLine +
Environment.NewLine + tenantMigrationOutput;
Logger.LogError(exceptionMsg);
throw new Exception(exceptionMsg);
}
}
private string FindTenantDbContextName(string dbMigrationsFolder)
{
var tenantDbContext = Directory
.GetFiles(dbMigrationsFolder, "*TenantMigrationsDbContext.cs", SearchOption.AllDirectories)
.FirstOrDefault();
if (tenantDbContext == null)
{
return null;
}
return Path.GetFileName(tenantDbContext).RemovePostFix(".cs");
}
private string FindDbContextName(string dbMigrationsFolder)
{
var dbContext = Directory
.GetFiles(dbMigrationsFolder, "*MigrationsDbContext.cs", SearchOption.AllDirectories)
.FirstOrDefault(fp => !fp.EndsWith("TenantMigrationsDbContext.cs"));
if (dbContext == null)
{
return null;
}
return Path.GetFileName(dbContext).RemovePostFix(".cs");
}
private static string AddMigrationAndGetOutput(string dbMigrationsFolder, string dbContext, string outputDirectory)
{
var dbContextOption = string.IsNullOrWhiteSpace(dbContext)
? string.Empty
: $"--context {dbContext}";
var addMigrationCmd = $"cd \"{dbMigrationsFolder}\" && " +
$"dotnet ef migrations add Initial --output-dir {outputDirectory} {dbContextOption}";
return CmdHelper.RunCmdAndGetOutput(addMigrationCmd);
}
private static bool IsDotNetEfToolInstalled()
{
var output = CmdHelper.RunCmdAndGetOutput("dotnet tool list -g");
return output.Contains("dotnet-ef");
}
private static bool CheckMigrationOutput(string output)
{
return output == null || (output.Contains("Done.") &&
output.Contains("To undo this action") &&
output.Contains("ef migrations remove"));
}
private void InstallDotnetEfTool()
{
Logger.LogInformation("Installing dotnet-ef tool...");
@ -95,4 +149,4 @@ namespace Volo.Abp.Cli.Commands
return string.Empty;
}
}
}
}

9
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/DatabaseManagementSystemChangeStep.cs

@ -54,7 +54,8 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
private void AdjustOracleDbContextOptionsBuilder(ProjectBuildContext context)
{
var dbContextFactoryFile = context.Files.First(f => f.Name.EndsWith("MigrationsDbContextFactory.cs", StringComparison.OrdinalIgnoreCase));
var dbContextFactoryFile = context.Files.FirstOrDefault(f => f.Name.EndsWith("MigrationsDbContextFactoryBase.cs", StringComparison.OrdinalIgnoreCase))
?? context.Files.First(f => f.Name.EndsWith("MigrationsDbContextFactory.cs", StringComparison.OrdinalIgnoreCase));
dbContextFactoryFile.ReplaceText("new DbContextOptionsBuilder",
$"(DbContextOptionsBuilder<{context.BuildArgs.SolutionName.ProjectName}MigrationsDbContext>) new DbContextOptionsBuilder");
@ -62,7 +63,8 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
private void AddMySqlServerVersion(ProjectBuildContext context)
{
var dbContextFactoryFile = context.Files.First(f => f.Name.EndsWith("MigrationsDbContextFactory.cs", StringComparison.OrdinalIgnoreCase));
var dbContextFactoryFile = context.Files.FirstOrDefault(f => f.Name.EndsWith("MigrationsDbContextFactoryBase.cs", StringComparison.OrdinalIgnoreCase))
?? context.Files.First(f => f.Name.EndsWith("MigrationsDbContextFactory.cs", StringComparison.OrdinalIgnoreCase));
dbContextFactoryFile.ReplaceText("configuration.GetConnectionString(\"Default\")",
"configuration.GetConnectionString(\"Default\"), MySqlServerVersion.LatestSupportedServerVersion");
@ -90,7 +92,8 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
var efCoreModuleClass = context.Files.First(f => f.Name.EndsWith("EntityFrameworkCoreModule.cs", StringComparison.OrdinalIgnoreCase));
efCoreModuleClass.ReplaceText(oldUseMethod, newUseMethodForEfModule);
var dbContextFactoryFile = context.Files.First(f => f.Name.EndsWith("MigrationsDbContextFactory.cs", StringComparison.OrdinalIgnoreCase));
var dbContextFactoryFile = context.Files.FirstOrDefault(f => f.Name.EndsWith("MigrationsDbContextFactoryBase.cs", StringComparison.OrdinalIgnoreCase))
?? context.Files.First(f => f.Name.EndsWith("MigrationsDbContextFactory.cs", StringComparison.OrdinalIgnoreCase));
dbContextFactoryFile.ReplaceText(oldUseMethod, newUseMethodForDbContext);
}
}

1
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/RemoveCmsKitStep.cs

@ -11,6 +11,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
f.Name.EndsWith(".csproj") ||
f.Name.EndsWith("Module.cs") ||
f.Name.EndsWith("MyProjectNameMigrationsDbContext.cs") ||
f.Name.EndsWith("MyProjectNameMigrationsDbContextBase.cs") ||
f.Name.EndsWith("MyProjectNameGlobalFeatureConfigurator.cs") ||
(f.Name.EndsWith(".cshtml") && f.Name.Contains("MyCompanyName.MyProjectName.Web.Public"))
);

15
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs

@ -24,6 +24,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App
{
var steps = new List<ProjectBuildPipelineStep>();
ConfigureTenantSchema(context, steps);
SwitchDatabaseProvider(context, steps);
DeleteUnrelatedProjects(context, steps);
RemoveMigrations(context, steps);
@ -38,6 +39,19 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App
return steps;
}
private static void ConfigureTenantSchema(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)
{
if (context.BuildArgs.ExtraProperties.ContainsKey("separate-tenant-schema"))
{
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations"));
steps.Add(new AppTemplateProjectRenameStep("MyCompanyName.MyProjectName.EntityFrameworkCore.SeparateDbMigrations", "MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations"));
}
else
{
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.EntityFrameworkCore.SeparateDbMigrations"));
}
}
private static void SwitchDatabaseProvider(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)
{
if (context.BuildArgs.DatabaseProvider == DatabaseProvider.MongoDb)
@ -284,6 +298,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App
SemanticVersion.Parse(context.BuildArgs.Version) > new SemanticVersion(4,1,99))
{
steps.Add(new RemoveFolderStep("/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/Migrations"));
steps.Add(new RemoveFolderStep("/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/TenantMigrations"));
}
}

59
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/EfCoreMigrationManager.cs

@ -17,14 +17,38 @@ namespace Volo.Abp.Cli.ProjectModification
Logger = NullLogger<EfCoreMigrationManager>.Instance;
}
public void AddMigration(string dbMigrationsCsprojFile, string module, string startupProject)
public void AddMigration(string dbMigrationsCsprojFile, string module)
{
var dbMigrationsProjectFolder = Path.GetDirectoryName(dbMigrationsCsprojFile);
var moduleName = ParseModuleName(module);
var migrationName = "Added_" + moduleName + "_Module" + GetUniquePostFix();
CmdHelper.RunCmd("cd \"" + Path.GetDirectoryName(dbMigrationsCsprojFile) +
"\" && dotnet ef migrations add " + migrationName +
GetStartupProjectOption(startupProject));
var tenantDbContextName = FindTenantDbContextName(dbMigrationsProjectFolder);
var dbContextName = tenantDbContextName != null ?
FindDbContextName(dbMigrationsProjectFolder)
: null;
if (!string.IsNullOrEmpty(tenantDbContextName))
{
RunAddMigrationCommand(dbMigrationsProjectFolder, migrationName, tenantDbContextName, "TenantMigrations");
}
RunAddMigrationCommand(dbMigrationsProjectFolder, migrationName, dbContextName, "Migrations");
}
protected virtual void RunAddMigrationCommand(
string dbMigrationsProjectFolder,
string migrationName,
string dbContext,
string outputDirectory)
{
var dbContextOption = string.IsNullOrWhiteSpace(dbContext)
? string.Empty
: $"--context {dbContext}";
CmdHelper.RunCmd($"cd \"{dbMigrationsProjectFolder}\" && dotnet ef migrations add {migrationName}" +
$" --output-dir {outputDirectory}" +
$" {dbContextOption}");
}
protected virtual string ParseModuleName(string fullModuleName)
@ -43,9 +67,32 @@ namespace Volo.Abp.Cli.ProjectModification
return "_" + new Random().Next(1, 99999);
}
protected virtual string GetStartupProjectOption(string startupProject)
protected virtual string FindDbContextName(string dbMigrationsFolder)
{
return startupProject.IsNullOrWhiteSpace() ? "" : $" -s {startupProject}";
var dbContext = Directory
.GetFiles(dbMigrationsFolder, "*MigrationsDbContext.cs", SearchOption.AllDirectories)
.FirstOrDefault(fp => !fp.EndsWith("TenantMigrationsDbContext.cs"));
if (dbContext == null)
{
return null;
}
return Path.GetFileName(dbContext).RemovePostFix(".cs");
}
protected virtual string FindTenantDbContextName(string dbMigrationsFolder)
{
var tenantDbContext = Directory
.GetFiles(dbMigrationsFolder, "*TenantMigrationsDbContext.cs", SearchOption.AllDirectories)
.FirstOrDefault();
if (tenantDbContext == null)
{
return null;
}
return Path.GetFileName(tenantDbContext).RemovePostFix(".cs");
}
}
}

13
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs

@ -78,7 +78,6 @@ namespace Volo.Abp.Cli.ProjectModification
public virtual async Task AddAsync(
[NotNull] string solutionFile,
[NotNull] string moduleName,
string startupProject,
string version,
bool skipDbMigrations = false,
bool withSourceCode = false,
@ -128,7 +127,7 @@ namespace Volo.Abp.Cli.ProjectModification
await RunBundleForBlazorAsync(projectFiles, module);
ModifyDbContext(projectFiles, module, startupProject, skipDbMigrations);
ModifyDbContext(projectFiles, module, skipDbMigrations);
}
private async Task RunBundleForBlazorAsync(string[] projectFiles, ModuleWithMastersInfo module)
@ -450,8 +449,7 @@ namespace Volo.Abp.Cli.ProjectModification
}
}
protected void ModifyDbContext(string[] projectFiles, ModuleInfo module, string startupProject,
bool skipDbMigrations = false)
protected void ModifyDbContext(string[] projectFiles, ModuleInfo module, bool skipDbMigrations = false)
{
if (string.IsNullOrWhiteSpace(module.EfCoreConfigureMethodName))
{
@ -463,11 +461,6 @@ namespace Volo.Abp.Cli.ProjectModification
return;
}
if (string.IsNullOrWhiteSpace(startupProject))
{
startupProject = projectFiles.FirstOrDefault(p => p.EndsWith(".DbMigrator.csproj"));
}
var dbMigrationsProject = projectFiles.FirstOrDefault(p => p.EndsWith(".DbMigrations.csproj"));
if (dbMigrationsProject == null)
@ -498,7 +491,7 @@ namespace Volo.Abp.Cli.ProjectModification
{
if (addedNewBuilder)
{
EfCoreMigrationManager.AddMigration(dbMigrationsProject, module.Name, startupProject);
EfCoreMigrationManager.AddMigration(dbMigrationsProject, module.Name);
}
RunMigrator(projectFiles);

Loading…
Cancel
Save