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( await SolutionModuleAdder.AddAsync(
solutionFile, solutionFile,
commandLineArgs.Target, commandLineArgs.Target,
commandLineArgs.Options.GetOrNull(Options.StartupProject.Short, Options.StartupProject.Long),
version, version,
skipDbMigrations, skipDbMigrations,
withSourceCode, withSourceCode,
@ -167,12 +166,6 @@ namespace Volo.Abp.Cli.Commands
public const string Skip = "skip-db-migrations"; 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 static class SourceCode
{ {
public const string Long = "with-source-code"; 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!"); throw new CliUsageException("DbMigrations folder path is missing!");
} }
var dbMigratorProjectPath = GetDbMigratorProjectPath(commandLineArgs.Target); var dbMigrationsFolder = commandLineArgs.Target;
var dbMigratorProjectPath = GetDbMigratorProjectPath(dbMigrationsFolder);
if (dbMigratorProjectPath == null) if (dbMigratorProjectPath == null)
{ {
throw new Exception("DbMigrator is not found!"); throw new Exception("DbMigrator is not found!");
@ -37,13 +39,17 @@ namespace Volo.Abp.Cli.Commands
InstallDotnetEfTool(); InstallDotnetEfTool();
} }
var addMigrationCmd = $"cd \"{commandLineArgs.Target}\" && " + var tenantDbContextName = FindTenantDbContextName(dbMigrationsFolder);
$"dotnet ef migrations add Initial -s \"{dbMigratorProjectPath}\""; 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 (CheckMigrationOutput(migrationOutput) && CheckMigrationOutput(tenantMigrationOutput))
if (output.Contains("Done.") &&
output.Contains("To undo this action") &&
output.Contains("ef migrations remove"))
{ {
// Migration added successfully // Migration added successfully
CmdHelper.RunCmd("cd \"" + Path.GetDirectoryName(dbMigratorProjectPath) + "\" && dotnet run"); CmdHelper.RunCmd("cd \"" + Path.GetDirectoryName(dbMigratorProjectPath) + "\" && dotnet run");
@ -51,22 +57,70 @@ namespace Volo.Abp.Cli.Commands
} }
else 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 + Environment.NewLine +
addMigrationCmd + Environment.NewLine + migrationOutput +
Environment.NewLine + output; Environment.NewLine +
Environment.NewLine + tenantMigrationOutput;
Logger.LogError(exceptionMsg); Logger.LogError(exceptionMsg);
throw new Exception(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() private static bool IsDotNetEfToolInstalled()
{ {
var output = CmdHelper.RunCmdAndGetOutput("dotnet tool list -g"); var output = CmdHelper.RunCmdAndGetOutput("dotnet tool list -g");
return output.Contains("dotnet-ef"); 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() private void InstallDotnetEfTool()
{ {
Logger.LogInformation("Installing dotnet-ef tool..."); Logger.LogInformation("Installing dotnet-ef tool...");
@ -95,4 +149,4 @@ namespace Volo.Abp.Cli.Commands
return string.Empty; 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) 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", dbContextFactoryFile.ReplaceText("new DbContextOptionsBuilder",
$"(DbContextOptionsBuilder<{context.BuildArgs.SolutionName.ProjectName}MigrationsDbContext>) 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) 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\")", dbContextFactoryFile.ReplaceText("configuration.GetConnectionString(\"Default\")",
"configuration.GetConnectionString(\"Default\"), MySqlServerVersion.LatestSupportedServerVersion"); "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)); var efCoreModuleClass = context.Files.First(f => f.Name.EndsWith("EntityFrameworkCoreModule.cs", StringComparison.OrdinalIgnoreCase));
efCoreModuleClass.ReplaceText(oldUseMethod, newUseMethodForEfModule); 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); 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(".csproj") ||
f.Name.EndsWith("Module.cs") || f.Name.EndsWith("Module.cs") ||
f.Name.EndsWith("MyProjectNameMigrationsDbContext.cs") || f.Name.EndsWith("MyProjectNameMigrationsDbContext.cs") ||
f.Name.EndsWith("MyProjectNameMigrationsDbContextBase.cs") ||
f.Name.EndsWith("MyProjectNameGlobalFeatureConfigurator.cs") || f.Name.EndsWith("MyProjectNameGlobalFeatureConfigurator.cs") ||
(f.Name.EndsWith(".cshtml") && f.Name.Contains("MyCompanyName.MyProjectName.Web.Public")) (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>(); var steps = new List<ProjectBuildPipelineStep>();
ConfigureTenantSchema(context, steps);
SwitchDatabaseProvider(context, steps); SwitchDatabaseProvider(context, steps);
DeleteUnrelatedProjects(context, steps); DeleteUnrelatedProjects(context, steps);
RemoveMigrations(context, steps); RemoveMigrations(context, steps);
@ -38,6 +39,19 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App
return steps; 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) private static void SwitchDatabaseProvider(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)
{ {
if (context.BuildArgs.DatabaseProvider == DatabaseProvider.MongoDb) 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)) 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/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; 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 moduleName = ParseModuleName(module);
var migrationName = "Added_" + moduleName + "_Module" + GetUniquePostFix(); var migrationName = "Added_" + moduleName + "_Module" + GetUniquePostFix();
CmdHelper.RunCmd("cd \"" + Path.GetDirectoryName(dbMigrationsCsprojFile) + var tenantDbContextName = FindTenantDbContextName(dbMigrationsProjectFolder);
"\" && dotnet ef migrations add " + migrationName + var dbContextName = tenantDbContextName != null ?
GetStartupProjectOption(startupProject)); 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) protected virtual string ParseModuleName(string fullModuleName)
@ -43,9 +67,32 @@ namespace Volo.Abp.Cli.ProjectModification
return "_" + new Random().Next(1, 99999); 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( public virtual async Task AddAsync(
[NotNull] string solutionFile, [NotNull] string solutionFile,
[NotNull] string moduleName, [NotNull] string moduleName,
string startupProject,
string version, string version,
bool skipDbMigrations = false, bool skipDbMigrations = false,
bool withSourceCode = false, bool withSourceCode = false,
@ -128,7 +127,7 @@ namespace Volo.Abp.Cli.ProjectModification
await RunBundleForBlazorAsync(projectFiles, module); await RunBundleForBlazorAsync(projectFiles, module);
ModifyDbContext(projectFiles, module, startupProject, skipDbMigrations); ModifyDbContext(projectFiles, module, skipDbMigrations);
} }
private async Task RunBundleForBlazorAsync(string[] projectFiles, ModuleWithMastersInfo module) 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, protected void ModifyDbContext(string[] projectFiles, ModuleInfo module, bool skipDbMigrations = false)
bool skipDbMigrations = false)
{ {
if (string.IsNullOrWhiteSpace(module.EfCoreConfigureMethodName)) if (string.IsNullOrWhiteSpace(module.EfCoreConfigureMethodName))
{ {
@ -463,11 +461,6 @@ namespace Volo.Abp.Cli.ProjectModification
return; return;
} }
if (string.IsNullOrWhiteSpace(startupProject))
{
startupProject = projectFiles.FirstOrDefault(p => p.EndsWith(".DbMigrator.csproj"));
}
var dbMigrationsProject = projectFiles.FirstOrDefault(p => p.EndsWith(".DbMigrations.csproj")); var dbMigrationsProject = projectFiles.FirstOrDefault(p => p.EndsWith(".DbMigrations.csproj"));
if (dbMigrationsProject == null) if (dbMigrationsProject == null)
@ -498,7 +491,7 @@ namespace Volo.Abp.Cli.ProjectModification
{ {
if (addedNewBuilder) if (addedNewBuilder)
{ {
EfCoreMigrationManager.AddMigration(dbMigrationsProject, module.Name, startupProject); EfCoreMigrationManager.AddMigration(dbMigrationsProject, module.Name);
} }
RunMigrator(projectFiles); RunMigrator(projectFiles);

Loading…
Cancel
Save