namespace Framework.Cli.Command
{
using Database.dbo;
using Framework.Cli.Config;
using Framework.DataAccessLayer;
using Microsoft.Data.SqlClient;
using Microsoft.Extensions.CommandLineUtils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using static Framework.Cli.AppCli;
using static Framework.DataAccessLayer.UtilDalUpsertIntegrate;
///
/// Cli deployDb command.
///
internal class CommandDeployDb : CommandBase
{
public CommandDeployDb(AppCli appCli)
: base(appCli, "deployDb", "Deploy database by running sql scripts")
{
}
private CommandOption optionDrop;
private CommandOption optionSilent;
private CommandOption optionReseed;
private CommandOption optionOnly;
protected internal override void Register(CommandLineApplication configuration)
{
optionDrop = configuration.Option("-d|--drop", "Drop sql tables and views.", CommandOptionType.NoValue);
optionSilent = configuration.Option("-s|--silent", "No command line user interaction.", CommandOptionType.NoValue);
optionReseed = configuration.Option("-r|--reseed", "Reseed Integrate records.", CommandOptionType.NoValue);
optionOnly = configuration.Option("-o|--only", "Do not run integrate program.", CommandOptionType.NoValue);
}
///
/// Returns true if fileName ends with Drop.sql
///
private bool IsFileNameDrop(string fileName)
{
return fileName.ToLower().EndsWith("drop.sql");
}
///
/// Execute (*.sql) scripts.
///
private void DeployDbExecute(string folderName, bool isFrameworkDb)
{
// SELECT FrameworkDeployDb
var rowList = Data.Query().QueryExecute();
// FileNameList. For example "Framework/Framework.Cli/DeployDb/Config.sql"
List fileNameList = new List();
foreach (string fileName in UtilFramework.FileNameList(folderName, "*.sql"))
{
UtilFramework.Assert(fileName.ToLower().StartsWith(UtilFramework.FolderName.ToLower()));
if (!IsFileNameDrop(fileName))
{
fileNameList.Add(fileName.Substring(UtilFramework.FolderName.Length));
}
}
fileNameList = fileNameList.OrderBy(item => item).ToList();
foreach (string fileName in fileNameList)
{
if (rowList.Select(item => item.FileName.ToLower()).Contains(fileName.ToLower()) == false)
{
string fileNameFull = UtilFramework.FolderName + fileName;
Console.WriteLine(string.Format("Execute {0}", fileNameFull));
string sql = UtilFramework.FileLoad(fileNameFull);
Data.ExecuteNonQueryAsync(sql, null, isFrameworkDb, commandTimeout: 0).Wait();
FrameworkDeployDb row = new FrameworkDeployDb() { FileName = fileName, Date = DateTime.UtcNow };
Data.InsertAsync(row).Wait();
}
}
}
///
/// Execute (*Drop.sql) scripts.
///
private void DeployDbDropExecute(string folderName, bool isFrameworkDb)
{
// FileNameList. For example "Framework/Framework.Cli/DeployDb/Config.sql"
List fileNameList = new List();
foreach (string fileName in UtilFramework.FileNameList(folderName, "*.sql"))
{
UtilFramework.Assert(fileName.ToLower().StartsWith(UtilFramework.FolderName.ToLower()));
if (IsFileNameDrop(fileName))
{
fileNameList.Add(fileName.Substring(UtilFramework.FolderName.Length));
}
}
fileNameList = fileNameList.OrderByDescending(item => item).ToList(); // Reverse
foreach (string fileName in fileNameList)
{
string fileNameFull = UtilFramework.FolderName + fileName;
Console.WriteLine(string.Format("Execute {0}", fileNameFull));
string sql = UtilFramework.FileLoad(fileNameFull);
try
{
Data.ExecuteNonQueryAsync(sql, null, isFrameworkDb, commandTimeout: 0).Wait();
}
catch
{
UtilCliInternal.ConsoleWriteLineColor("Warning! Already dropped or drop failed!", ConsoleColor.Yellow); // Warning
}
}
}
///
/// Populate sql tables FrameworkTable, FrameworkField with assembly typeRow.
///
private void Meta(DeployDbIntegrateResult result)
{
var assemblyList = AppCli.AssemblyList(isIncludeApp: true);
List typeRowList = UtilDalType.TypeRowList(assemblyList);
// Table
{
List rowList = new List();
foreach (Type typeRow in typeRowList)
{
FrameworkTable table = new FrameworkTable();
rowList.Add(table);
table.TableNameCSharp = UtilDalType.TypeRowToTableNameCSharp(typeRow);
if (UtilDalType.TypeRowIsTableNameSql(typeRow))
{
table.TableNameSql = UtilDalType.TypeRowToTableNameWithSchemaSql(typeRow);
}
table.IsDelete = false;
}
result.Add(rowList);
}
// Field
{
List rowList = new List();
foreach (Type typeRow in typeRowList)
{
string tableNameCSharp = UtilDalType.TypeRowToTableNameCSharp(typeRow);
var fieldList = UtilDalType.TypeRowToFieldList(typeRow);
foreach (var field in fieldList)
{
FrameworkFieldIntegrate fieldIntegrate = new FrameworkFieldIntegrate();
rowList.Add(fieldIntegrate);
fieldIntegrate.TableIdName = tableNameCSharp;
fieldIntegrate.FieldNameCSharp = field.PropertyInfo.Name;
fieldIntegrate.FieldNameSql = field.FieldNameSql;
fieldIntegrate.Sort = field.Sort;
fieldIntegrate.IsDelete = false;
}
}
rowList = rowList.OrderBy(item => item.TableIdName).ThenBy(item => item.FieldNameCSharp).ToList();
result.Add(rowList);
}
}
///
/// Resedd sql table for Integrate.
///
private void IntegrateReseed(List upsertList, int? reseed, List assemblyList)
{
if (reseed != null)
{
foreach (var item in upsertList)
{
if (item.IsDeploy == false)
{
Type typeRowDest = item.TypeRowDest(assemblyList);
UtilDalType.TypeRowToTableNameSql(typeRowDest, out string schemaNameSql, out string tableNameSql);
string tableNameWithSchemaSql = UtilDalType.TableNameWithSchemaSql(schemaNameSql, tableNameSql);
bool isFrameworkDb = UtilDalType.TypeRowIsFrameworkDb(item.TypeRow);
var paramList = new List<(FrameworkTypeEnum FrameworkTypeEnum, SqlParameter SqlParameter)>();
string paramNameTableNameCSharp = Data.ExecuteParamAdd(FrameworkTypeEnum.Nvarcahr, tableNameWithSchemaSql, paramList);
string paramNameReseed = Data.ExecuteParamAdd(FrameworkTypeEnum.Bigint, (long)reseed, paramList);
string sql = string.Format("DBCC checkident ({0}, reseed, {1})", paramNameTableNameCSharp, paramNameReseed);
Data.ExecuteNonQueryAsync(sql, paramList, isFrameworkDb).Wait();
}
}
}
}
///
/// Populate sql Integrate tables.
///
private void Integrate(int? reseed)
{
var generateIntegrateResult = AppCli.CommandGenerateIntegrateInternal(isDeployDb: true, null);
var deployDbResult = new DeployDbIntegrateResult(generateIntegrateResult);
List assemblyList = AppCli.AssemblyList(isIncludeApp: true, isIncludeFrameworkCli: true);
// Populate sql tables FrameworkTable, FrameworkField.
UtilCliInternal.ConsoleWriteLineColor("Update FrameworkTable, FrameworkField tables", ConsoleColor.Green);
Meta(deployDbResult);
IntegrateReseed(deployDbResult.Result, reseed, assemblyList);
UtilDalUpsertIntegrate.UpsertAsync(deployDbResult.Result, assemblyList).Wait();
// Populate sql Integrate tables.
UtilCliInternal.ConsoleWriteLineColor("Update Integrate tables ", ConsoleColor.Green, isLine: false);
AppCli.CommandDeployDbIntegrateInternal(deployDbResult);
IntegrateReseed(deployDbResult.Result, reseed, assemblyList);
UtilDalUpsertIntegrate.UpsertAsync(deployDbResult.Result, assemblyList, (typeRow) => UtilCliInternal.ConsoleWriteLineColor(".", ConsoleColor.Green, isLine: false)).Wait(); // See also property IsDeploy
Console.WriteLine();
}
protected internal override void Execute()
{
ConfigCli configCli = ConfigCli.Load();
if (UtilExternalGit.IsExternalGit)
{
Console.WriteLine("For ExternalGit run command wpx ExternalGit and then command wpx deploy on main application (because of shared table FrameworkDeplayDb and FrameworkConfig).");
if (UtilCliInternal.ConsoleReadYesNo("Continue anyway?") == false)
{
return;
}
}
if (optionSilent.OptionGet() == false && configCli.EnvironmentNameGet() != "DEV")
{
if (UtilCliInternal.ConsoleReadYesNo(string.Format("Deploy to {0} database?", configCli.EnvironmentName)) == false)
{
return;
}
}
if (optionDrop.OptionGet())
{
// FolderNameDeployDb
string folderNameDeployDbFramework = UtilFramework.FolderName + "Framework/Framework.Cli/DeployDb/";
string folderNameDeployDbApplication = UtilFramework.FolderName + "Application.Cli/DeployDb/";
Console.WriteLine("DeployDbDrop");
DeployDbDropExecute(folderNameDeployDbApplication, isFrameworkDb: false);
DeployDbDropExecute(folderNameDeployDbFramework, isFrameworkDb: true); // Uses ConnectionString in ConfigServer.json
UtilCliInternal.ConsoleWriteLineColor("DeployDb drop successful!", ConsoleColor.Green);
}
else
{
// FolderNameDeployDb
string folderNameDeployDbFramework = UtilFramework.FolderName + "Framework/Framework.Cli/DeployDb/";
string folderNameDeployDbApplication = UtilFramework.FolderName + "Application.Cli/DeployDb/";
// SqlInit
string fileNameInit = UtilFramework.FolderName + "Framework/Framework.Cli/DeployDbInit/Init.sql";
string sqlInit = UtilFramework.FileLoad(fileNameInit);
Data.ExecuteNonQueryAsync(sqlInit, null, isFrameworkDb: true).Wait();
// (*.sql)
UtilCliInternal.ConsoleWriteLineColor("DeployDb run (*.sql) scripts", ConsoleColor.Green);
DeployDbExecute(folderNameDeployDbFramework, isFrameworkDb: true); // Uses ConnectionString in ConfigServer.json
DeployDbExecute(folderNameDeployDbApplication, isFrameworkDb: false);
UtilCliInternal.ConsoleWriteLineColor("DeployDb run (*.sql) scripts successful!", ConsoleColor.Green);
if (!optionOnly.OptionGet())
{
// Integrate
UtilCliInternal.ConsoleWriteLineColor("DeployDb run Integrate", ConsoleColor.Green);
int? reseed = null;
if (optionReseed.OptionGet())
{
reseed = 1000;
}
Integrate(reseed);
UtilCliInternal.ConsoleWriteLineColor("DeployDb run Integrate successful!", ConsoleColor.Green);
}
}
}
}
}