CLI can configure Entity Framework after installing a module

Resolves https://github.com/abpframework/abp/issues/1122
pull/1126/head
Yunus Emre Kalkan 6 years ago
parent 92f5bc65d1
commit 8d7b490127

@ -30,9 +30,13 @@ namespace Volo.Abp.Cli.Commands
throw new CliUsageException("Module name is missing!" + Environment.NewLine + Environment.NewLine + GetUsageInfo()); throw new CliUsageException("Module name is missing!" + Environment.NewLine + Environment.NewLine + GetUsageInfo());
} }
var skipDbMigrations = Convert.ToBoolean(
commandLineArgs.Options.GetOrNull(Options.Solution.SkipDbMigrations) ?? "false");
await SolutionModuleAdder.AddAsync( await SolutionModuleAdder.AddAsync(
GetSolutionFile(commandLineArgs), GetSolutionFile(commandLineArgs),
commandLineArgs.Target commandLineArgs.Target,
skipDbMigrations
); );
} }
@ -93,6 +97,7 @@ namespace Volo.Abp.Cli.Commands
sb.AppendLine("Examples:"); sb.AppendLine("Examples:");
sb.AppendLine(" abp add-module Volo.Blogging Adds the module to the current soluton."); sb.AppendLine(" abp add-module Volo.Blogging Adds the module to the current soluton.");
sb.AppendLine(" abp add-module Volo.Blogging -s Acme.BookStore Adds the module to the given soluton."); sb.AppendLine(" abp add-module Volo.Blogging -s Acme.BookStore Adds the module to the given soluton.");
sb.AppendLine(" abp add-module Volo.Blogging -s Acme.BookStore --SkipDbMigrations false Adds the module to the given soluton but doesn't add-migration.");
sb.AppendLine(""); sb.AppendLine("");
return sb.ToString(); return sb.ToString();
@ -104,6 +109,7 @@ namespace Volo.Abp.Cli.Commands
{ {
public const string Short = "s"; public const string Short = "s";
public const string Long = "solution"; public const string Long = "solution";
public const string SkipDbMigrations = "skip-db-migrations";
} }
} }
} }

@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.ProjectModification
{
public class DbContextFileBuilderConfigureAdder : ITransientDependency
{
public void Add(string path, string moduleConfiguration)
{
var file = File.ReadAllText(path);
var indexToInsert = FindIndexToInsert(file);
var stringToAdd = GetLineToAdd(moduleConfiguration);
stringToAdd = " " + stringToAdd + Environment.NewLine;
file = file.Insert(indexToInsert, stringToAdd);
File.WriteAllText(path, file);
}
protected int FindIndexToInsert(string file)
{
var indexOfMethodDeclaration = file.IndexOf("OnModelCreating(", StringComparison.Ordinal);
var indexOfOpeningBracket = indexOfMethodDeclaration + file.Substring(indexOfMethodDeclaration).IndexOf('{');
var stack = 1;
var index = indexOfOpeningBracket;
while (stack > 0 || index < file.Length)
{
index++;
if (file[index] == '{')
{
stack++;
}
else if (file[index] == '}')
{
stack--;
}
}
return index;
}
protected string GetLineToAdd(string moduleConfiguration)
{
return "builder.Configure" + moduleConfiguration + "();";
}
}
}

@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.ProjectModification
{
public class EfCoreMigrationAdder : ITransientDependency
{
public void AddMigration(string csprojFile, string module, bool updateDatabase = true)
{
var moduleName = ParseModuleName(module);
var migrationName = "Added_" + moduleName + "_Module" + GetUniquePostFix();
var process = Process.Start("CMD.exe", "/C cd \"" + csprojFile + "\" & dotnet ef migrations add " + migrationName);
process.WaitForExit();
if (updateDatabase)
{
UpdateDatabase(csprojFile);
}
}
protected void UpdateDatabase(string csprojFile)
{
var process = Process.Start("CMD.exe", "/C cd \"" + csprojFile + "\" & dotnet ef database update");
process.WaitForExit();
}
protected virtual string ParseModuleName(string fullModuleName)
{
var words = fullModuleName?.Split('.');
if (words == null || words.Length <= 1)
{
return "";
}
return words[words.Length - 1];
}
protected virtual string GetUniquePostFix()
{
return "_" + new Random().Next(1,99999);
}
}
}

@ -8,6 +8,8 @@ namespace Volo.Abp.Cli.ProjectModification
public string DisplayName { get; set; } public string DisplayName { get; set; }
public string EfCoreConfigureMethodName { get; set; }
public List<NugetPackageInfo> NugetPackages { get; set; } public List<NugetPackageInfo> NugetPackages { get; set; }
public List<NpmPackageInfo> NpmPackages { get; set; } public List<NpmPackageInfo> NpmPackages { get; set; }

@ -19,22 +19,32 @@ namespace Volo.Abp.Cli.ProjectModification
protected IJsonSerializer JsonSerializer { get; } protected IJsonSerializer JsonSerializer { get; }
protected ProjectNugetPackageAdder ProjectNugetPackageAdder { get; } protected ProjectNugetPackageAdder ProjectNugetPackageAdder { get; }
protected DbContextFileBuilderConfigureAdder DbContextFileBuilderConfigureAdder { get; }
protected EfCoreMigrationAdder EfCoreMigrationAdder { get; }
protected ProjectNpmPackageAdder ProjectNpmPackageAdder { get; } protected ProjectNpmPackageAdder ProjectNpmPackageAdder { get; }
protected DerivedClassFinder DerivedClassFinder { get; }
public SolutionModuleAdder( public SolutionModuleAdder(
IJsonSerializer jsonSerializer, IJsonSerializer jsonSerializer,
ProjectNugetPackageAdder projectNugetPackageAdder, ProjectNugetPackageAdder projectNugetPackageAdder,
DbContextFileBuilderConfigureAdder dbContextFileBuilderConfigureAdder,
EfCoreMigrationAdder efCoreMigrationAdder,
DerivedClassFinder derivedClassFinder,
ProjectNpmPackageAdder projectNpmPackageAdder) ProjectNpmPackageAdder projectNpmPackageAdder)
{ {
EfCoreMigrationAdder = efCoreMigrationAdder;
DerivedClassFinder = derivedClassFinder;
JsonSerializer = jsonSerializer; JsonSerializer = jsonSerializer;
ProjectNugetPackageAdder = projectNugetPackageAdder; ProjectNugetPackageAdder = projectNugetPackageAdder;
DbContextFileBuilderConfigureAdder = dbContextFileBuilderConfigureAdder;
ProjectNpmPackageAdder = projectNpmPackageAdder; ProjectNpmPackageAdder = projectNpmPackageAdder;
Logger = NullLogger<SolutionModuleAdder>.Instance; Logger = NullLogger<SolutionModuleAdder>.Instance;
} }
public virtual async Task AddAsync( public virtual async Task AddAsync(
[NotNull] string solutionFile, [NotNull] string solutionFile,
[NotNull] string moduleName) [NotNull] string moduleName,
bool skipDbMigrations = false)
{ {
Check.NotNull(solutionFile, nameof(solutionFile)); Check.NotNull(solutionFile, nameof(solutionFile));
Check.NotNull(moduleName, nameof(moduleName)); Check.NotNull(moduleName, nameof(moduleName));
@ -75,8 +85,42 @@ namespace Volo.Abp.Cli.ProjectModification
Logger.LogDebug("Target project is not available for NPM packages."); Logger.LogDebug("Target project is not available for NPM packages.");
} }
} }
ModifyDbContext(projectFiles, module, skipDbMigrations);
}
protected void ModifyDbContext(string[] projectFiles, ModuleInfo module, bool skipDbMigrations = false)
{
if (string.IsNullOrWhiteSpace(module.EfCoreConfigureMethodName))
{
return;
}
var dbMigrationsProject = projectFiles.FirstOrDefault(p => p.EndsWith(".DbMigrations.csproj"));
if (dbMigrationsProject == null)
{
Logger.LogDebug("Solution doesn't have a \".DbMigrations\" project.");
return;
}
var dbContextFile = DerivedClassFinder.Find(dbMigrationsProject, "AbpDbContext").FirstOrDefault();
if (dbContextFile == null)
{
Logger.LogDebug($"{dbMigrationsProject} project doesn't have a class that is derived from \"AbpDbContext\".");
return;
}
DbContextFileBuilderConfigureAdder.Add(dbContextFile, module.EfCoreConfigureMethodName);
if (!skipDbMigrations)
{
EfCoreMigrationAdder.AddMigration(dbMigrationsProject, module.Name);
}
} }
protected virtual async Task<ModuleInfo> FindModuleInfoAsync(string moduleName) protected virtual async Task<ModuleInfo> FindModuleInfoAsync(string moduleName)
{ {
using (var client = new HttpClient()) using (var client = new HttpClient())

Loading…
Cancel
Save