860 lines
46 KiB
C#
860 lines
46 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text.RegularExpressions;
|
|
using Sarand.Net.Standard.Base.App;
|
|
using Sarand.Net.Standard.Base.Core;
|
|
using Sarand.Net.Standard.Base.Dbas;
|
|
using Sarand.Net.Standard.Base.IO;
|
|
using Sarand.Net.Standard.Base.Utils;
|
|
|
|
namespace Sarand.Net.Standard.Dbas.Base
|
|
{
|
|
//=======================================================================
|
|
public class DatabaseDefinitionGenerator
|
|
{
|
|
//-------------------------------------------------------------------
|
|
// Configuration.
|
|
public enum SarandCommonVersion
|
|
{
|
|
VS2017,
|
|
/// <summary>
|
|
/// Visual Studio 2019 version. StringListUtil rather than StringList.
|
|
/// </summary>
|
|
VS2019
|
|
}
|
|
public enum DotNetVersion
|
|
{
|
|
Framework,
|
|
Core3,
|
|
}
|
|
public enum Dbms
|
|
{
|
|
ODBC,
|
|
SQL,
|
|
}
|
|
public class Config
|
|
{
|
|
public SarandCommonVersion SarandCommonVersion { get; set; } = SarandCommonVersion.VS2019;
|
|
public DotNetVersion DotNetVersion { get; set; } = DotNetVersion.Framework;
|
|
public SacsDatabase Database { get; set; }
|
|
public Dbms DbmsOutput { get; set; } = Dbms.ODBC;
|
|
public String OutputDirectory { get; set; } = "";
|
|
public bool ConfirmDirectoryClear { get; set; } = true;
|
|
// Database schema.
|
|
public class SchemaData
|
|
{
|
|
// Tables to be included (all others excluded) or those to be excluded.
|
|
public HashSet<String> Tables_Included { get; } = new HashSet<String>(StringComparer.InvariantCultureIgnoreCase);
|
|
public HashSet<String> Tables_Excluded { get; } = new HashSet<String>(StringComparer.InvariantCultureIgnoreCase);
|
|
// Schema capitalisation - for class name prefix etc - where capitalising first letter is insufficient.
|
|
public Dictionary<String, String> SchemaNameCapitalisation { get; } = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
|
|
// Alternative table names.
|
|
public Dictionary<String, List<String>> AlternativeTableNames { get; } = new Dictionary<string, List<string>>(StringComparer.InvariantCultureIgnoreCase);
|
|
public void AddAlternativeTableName(String tableName, String tableNameAlternative)
|
|
{
|
|
if (!AlternativeTableNames.ContainsKey(tableName)) AlternativeTableNames[tableName] = new List<string>();
|
|
AlternativeTableNames[tableName].Add(tableNameAlternative);
|
|
}
|
|
// Insert only columns - not modified on update:
|
|
// Table name - regular expressions allowed.
|
|
// Comma separated list of columns
|
|
// eg. New StringPair(".*","CreateOn,CreateBy");
|
|
public List<StringPair> InsertOnlyColumns { get; } = new List<StringPair>();
|
|
}
|
|
public SchemaData Schema { get; } = new SchemaData();
|
|
// Database definition class.
|
|
public class DefinitionClassConfig
|
|
{
|
|
/// <summary>Using namespaces for database definition and table class usings.</summary>
|
|
public HashSet<String> Usings { get; } = new HashSet<String>() { "Sarand.Net.Standard.Base.Core", "Sarand.Net.Standard.Base.Dbas" };
|
|
public String Namespace { get; set; } = "Sarand.Application.Core.Base";
|
|
public String Classname { get; set; } = "SaDbDfn";
|
|
}
|
|
public DefinitionClassConfig DefinitionClass { get; } = new DefinitionClassConfig();
|
|
// Table class.
|
|
public class TableClassConfig
|
|
{
|
|
/// <summary>Using namespaces for table classes.</summary>
|
|
public HashSet<String> Usings { get; } = new HashSet<String>() { "Sarand.Net.Standard.Base.Core", "Sarand.Net.Standard.Base.Dbas" };
|
|
public String Namespace_BaseClass { get; set; } = "Sarand.Net.Standard.Dbas.Data";
|
|
public String Namespace { get; set; } = "Sarand.Application.Dbas";
|
|
public String BaseClass { get; set; } = "DbDataItem";
|
|
public String ClassName_DatabaseInfo = "IDbDataItem.IDatabaseInfo";
|
|
public bool MandatoryConstructorDbInfo = false;
|
|
public bool TreatDoubleFormatAsDecimal { get; set; } = false;
|
|
}
|
|
public TableClassConfig TableClass { get; } = new TableClassConfig();
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Data members.
|
|
private Config config = null;
|
|
private const String DefaultSchema_MSSQL = "dbo";
|
|
private static String /*lf = "\n",*/ crlf = "\r\n", tab1 = "\t", tab2 = "\t\t", tab3 = "\t\t\t", tab4 = "\t\t\t\t", tab5 = "\t\t\t\t\t";
|
|
// Reserved words.
|
|
private static readonly String[] reservedWords =
|
|
{
|
|
"ADD", "ALL", "ALTER", "AND", "ANY", "AS", "ASC", "AVG", "BEGIN", "BETWEEN", "BY", "CASE", "CAST", "COLUMN", "COMMIT", "CONSTRAINT",
|
|
"CONVERT", "COUNT", "CREATE", "CURRENCY", "DEFAULT", "DELETE", "DESC", "DISTINCT", "DROP", "ELSE", "END", "EXECUTE", "EXISTS", "FALSE",
|
|
"FROM", "GRANT", "GROUP", "HAVING", "IN", "INDEX", "INNER", "INSERT", "INTO", "IS", "JOIN", "KEY", "LEFT", "LIKE", "MAX", "MIN", "NOT",
|
|
"NULL", "ON", "OR", "ORDER", "OUTER", "OUTPUT", "PRIMARY", "PROCEDURE", "REVOKE", "ROLLBACK", "ROWCOUNT", "SELECT", "SET", "SQL", "SUM",
|
|
"TABLE", "THEN", "TRANSACTION", "TRUE", "UNION", "UNIQUE", "UPDATE", "USER", "VALUES", "VIEW", "WHEN", "WHERE"
|
|
};
|
|
|
|
//-------------------------------------------------------------------
|
|
public bool Generate(Config config)
|
|
{
|
|
// Validate configuration.
|
|
this.config = config;
|
|
if (!FileUtil.IsDirectory(config.OutputDirectory))
|
|
throw new Exception("Invalid directory specified [" + config.OutputDirectory + "]");
|
|
|
|
// Validate and cleanse configuration parameters.
|
|
if (StringUtil.IsEmpty(StringUtil.TrimAll(config.TableClass.BaseClass)))
|
|
config.TableClass.BaseClass = "DbDataItem";
|
|
|
|
// Clear files from output firectory.
|
|
if (Directory.EnumerateFiles(config.OutputDirectory, "*", SearchOption.TopDirectoryOnly).Count() > 0)
|
|
{
|
|
SaLogger.Info($"{SysUtil.Fn} Deleting existing files in output folders.");
|
|
DirectoryInfo di = new DirectoryInfo(config.OutputDirectory);
|
|
foreach (FileInfo file in di.EnumerateFiles())
|
|
file.Delete();
|
|
}
|
|
|
|
// Table definitions.
|
|
List<DbDfnTable> tableDfns = new List<DbDfnTable>();
|
|
foreach (DbDfnTable tableDfn in config.Database.GetTableDfns())
|
|
{
|
|
if (!IsValidTable(tableDfn.Name)) continue;
|
|
tableDfns.Add(tableDfn);
|
|
}
|
|
|
|
// Database schema XML.
|
|
GenerateDatabaseSchemaXml(tableDfns);
|
|
|
|
// Database definition class.
|
|
GenerateDatabaseDefinitionClass(tableDfns);
|
|
|
|
// Database table Classes.
|
|
foreach (DbDfnTable tableDfn in tableDfns)
|
|
GenerateTableInterfaceClass(tableDfn);
|
|
return true;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
private bool IsValidTable(String table)
|
|
{
|
|
if (String.IsNullOrEmpty(table)) return false;
|
|
if (config.Schema.Tables_Included.Count > 0 && !config.Schema.Tables_Included.ContainsCI(table)) return false;
|
|
if (config.Schema.Tables_Excluded.Count > 0 && config.Schema.Tables_Excluded.ContainsCI(table)) return false;
|
|
return true;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
private void GenerateDatabaseSchemaXml(List<DbDfnTable> tableDfns)
|
|
{
|
|
String filePath = config.OutputDirectory + Path.DirectorySeparatorChar + config.DefinitionClass.Classname + ".xml";
|
|
// Construct database definition.
|
|
DbDfnDatabase databaseDfn = new DbDfnDatabase();
|
|
foreach (DbDfnTable tableDfn in tableDfns)
|
|
{
|
|
databaseDfn.AddTable(tableDfn);
|
|
}
|
|
using (StreamWriter file = new StreamWriter(filePath))
|
|
{
|
|
file.Write(SerializableUtil.ToXml(databaseDfn));
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
/// <summary>Intercept column variable type name to replace double/float with decimal where required.</summary>
|
|
private String GetColumnVariableTypeName(DbDfnColumn columnDfn)
|
|
{
|
|
return GetColumnVariableTypeName(columnDfn, config.TableClass.TreatDoubleFormatAsDecimal);
|
|
}
|
|
/// <summary>Intercept column variable type name to replace double/float with decimal where required.</summary>
|
|
private static String GetColumnVariableTypeName(DbDfnColumn columnDfn, bool treatDoubleFormatAsDecimal)
|
|
{
|
|
String typeName = columnDfn.GetVariableTypeName();
|
|
if (treatDoubleFormatAsDecimal)
|
|
{
|
|
switch (columnDfn.DataType)
|
|
{
|
|
case DbColumnDataType.Single:
|
|
case DbColumnDataType.Double:
|
|
typeName = "Decimal";
|
|
break;
|
|
}
|
|
}
|
|
return typeName;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
/// <summary>Intercept column variable type to replace double/float with decimal where required.</summary>
|
|
private String GetColumnVariableType(DbDfnColumn columnDfn)
|
|
{
|
|
return GetColumnVariableType(columnDfn, config.TableClass.TreatDoubleFormatAsDecimal);
|
|
}
|
|
/// <summary>Intercept column variable type to replace double/float with decimal where required.</summary>
|
|
private static String GetColumnVariableType(DbDfnColumn columnDfn, bool treatDoubleFormatAsDecimal)
|
|
{
|
|
String typeName = columnDfn.GetVariableType();
|
|
if (treatDoubleFormatAsDecimal)
|
|
{
|
|
switch (columnDfn.DataType)
|
|
{
|
|
case DbColumnDataType.Single:
|
|
case DbColumnDataType.Double:
|
|
typeName = "Decimal";
|
|
break;
|
|
}
|
|
}
|
|
return typeName;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
/// <summary>Intercept column 'Get Field Suffix' to replace double/float with decimal where required.</summary>
|
|
private String GetColumnGetFieldSuffix(DbDfnColumn columnDfn)
|
|
{
|
|
return GetColumnGetFieldSuffix(columnDfn, config.TableClass.TreatDoubleFormatAsDecimal);
|
|
}
|
|
/// <summary>Intercept column 'Get Field Suffix' to replace double/float with decimal where required.</summary>
|
|
private static String GetColumnGetFieldSuffix(DbDfnColumn columnDfn, bool treatDoubleFormatAsDecimal)
|
|
{
|
|
String suffix = columnDfn.GetGetFieldSuffix();
|
|
if (treatDoubleFormatAsDecimal)
|
|
{
|
|
switch (columnDfn.DataType)
|
|
{
|
|
case DbColumnDataType.Single:
|
|
case DbColumnDataType.Double:
|
|
suffix = "Decimal";
|
|
break;
|
|
}
|
|
}
|
|
return suffix;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
private static List<string> nullableDataTypes = new List<string>() { "Boolean", "Byte", "Int16", "Int32", "Int64", "Single", "Double", "Decimal", "DateTime" };
|
|
/// <summary>
|
|
/// Determine whether column should be treated as nullable.
|
|
/// <para>- This behaviour is restricted to selected data types.</para>
|
|
/// </summary>
|
|
private bool TreatColumnAsNullable(DbDfnColumn columnDfn)
|
|
{
|
|
return (nullableDataTypes.ContainsCI(columnDfn.GetVariableTypeName()) && columnDfn.IsNullable);
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// D a t a b a s e D e f i n i t i o n C l a s s
|
|
//-------------------------------------------------------------------
|
|
private void GenerateDatabaseDefinitionClass(List<DbDfnTable> tableDfns)
|
|
{
|
|
String filePath = config.OutputDirectory + Path.DirectorySeparatorChar + config.DefinitionClass.Classname + ".cs";
|
|
using (StreamWriter file = new StreamWriter(filePath))
|
|
{
|
|
// Database definition file:
|
|
foreach (String namespace_Base in config.DefinitionClass.Usings.OrderBy(s => s))
|
|
file.WriteLine("using " + namespace_Base + ";");
|
|
file.WriteLine("using System;");
|
|
file.WriteLine("using System.Collections.Generic;");
|
|
file.WriteLine("using System.Linq;");
|
|
file.WriteLine("");
|
|
file.WriteLine("//---------------------------------------------------------------------------");
|
|
file.WriteLine("// Code generated by Sarand Database Utilities " + DateTime.Now.Format("ddd d-MMM-yyyy HH:mm:ss"));
|
|
file.WriteLine("//---------------------------------------------------------------------------");
|
|
file.WriteLine("namespace " + config.DefinitionClass.Namespace);
|
|
file.WriteLine("{");
|
|
file.WriteLine(tab1 + "public class " + config.DefinitionClass.Classname);
|
|
file.WriteLine(tab1 + "{");
|
|
file.WriteLine(tab2 + "//-------------------------------------------------------------------");
|
|
GenerateDatabaseDefinitionTablesEnum(tableDfns, file);
|
|
GenerateDatabaseDefinitionColumnsEnum(tableDfns, file);
|
|
GenerateDatabaseDefinitionClass(tableDfns, config.DefinitionClass.Classname, file);
|
|
file.WriteLine(tab1 + "}");
|
|
file.WriteLine("}");
|
|
//file.Close(); - Unecessary as the object will be disposed at the end of the 'using' block which is the same as Close.
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// D a t a b a s e E n u m s
|
|
//-------------------------------------------------------------------
|
|
public static void GenerateDatabaseDefinitionTablesEnum(List<DbDfnTable> tableDfns, StreamWriter file)
|
|
{
|
|
file.WriteLine(tab2 + "// Table identifiers.");
|
|
file.WriteLine(tab2 + "public enum TableIdx");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab3 + "Unknown = 0,");
|
|
foreach (DbDfnTable tableDfn in tableDfns)
|
|
{
|
|
file.WriteLine(tab3 + tableDfn.Name + ",");
|
|
}
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
public static void GenerateDatabaseDefinitionColumnsEnum(List<DbDfnTable> tableDfns, StreamWriter file)
|
|
{
|
|
file.WriteLine(tab2 + "// Column identifiers.");
|
|
file.WriteLine(tab2 + "public enum ColumnIdx");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab3 + "Unknown = 0,");
|
|
foreach (DbDfnTable tableDfn in tableDfns)
|
|
{
|
|
foreach (var columnDfn in tableDfn.Columns)
|
|
file.WriteLine(tab3 + tableDfn.Name + "_" + columnDfn.Name + ",");
|
|
}
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
public static void GenerateDatabaseDefinitionClass(List<DbDfnTable> tableDfns, String classnameDefinition, StreamWriter file)
|
|
{
|
|
file.WriteLine(tab2 + "// Data members.");
|
|
file.WriteLine(tab2 + "private static readonly int tableCount = " + tableDfns.Count + ";");
|
|
file.WriteLine(tab2 + "private static readonly int columnCount = " + tableDfns.GetColumnCount() + ";");
|
|
file.WriteLine(tab2 + "private static ulong maxTextLen = 0;");
|
|
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
|
|
|
// Table methods.
|
|
file.WriteLine(tab2 + "// Retrieve Table details (eg. name: 'Company').");
|
|
file.WriteLine(tab2 + "public static int GetTableCount ()");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab3 + "return tableCount;");
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(tab2 + "public static String GetTableName (TableIdx table, bool delimitReservedWords = true)");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab3 + "int tableIdx = (int)table - 1;");
|
|
file.WriteLine(tab3 + "if (tableIdx < 0 || tableIdx >= tableCount) return String.Empty;");
|
|
file.WriteLine(tab3 + "String tableName = tables[(int)tableIdx].Name;");
|
|
file.WriteLine(tab3 + "if (delimitReservedWords) tableName = DelimitReservedWord(tableName);");
|
|
file.WriteLine(tab3 + "return tableName;");
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(tab2 + "public static String GetTableNameQual (TableIdx table, bool delimitReservedWords = true)");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab3 + "int tableIdx = (int)table - 1;");
|
|
file.WriteLine(tab3 + "if (tableIdx < 0 || tableIdx >= tableCount) return String.Empty;");
|
|
file.WriteLine(tab3 + "String schemaName = tables[(int)tableIdx].Schema;");
|
|
file.WriteLine(tab3 + "String tableName = tables[(int)tableIdx].Name;");
|
|
file.WriteLine(tab3 + "if (delimitReservedWords) { schemaName = DelimitReservedWord(schemaName); tableName = DelimitReservedWord(tableName); }");
|
|
file.WriteLine(tab3 + "return (StringUtil.IsBlank(schemaName) ? \"\" : schemaName + \".\") + tableName;");
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
|
|
|
// Table for Column method.
|
|
file.WriteLine(tab2 + "// Identify the table that corresponds with the specified column.");
|
|
file.WriteLine(tab2 + "public static TableIdx GetTableForColumn (ColumnIdx column)");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab3 + "int columnIdx = (int)column - 1;");
|
|
file.WriteLine(tab3 + "if (columnIdx < 0 || columnIdx >= columnCount) return TableIdx.Unknown;");
|
|
file.WriteLine(tab3 + "return columns[columnIdx].TableIdx;");
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
|
|
|
// Column methods.
|
|
file.WriteLine(tab2 + "// Retrieve the specified Column's name (Qualified include table name: '(<Table>.Column>)').");
|
|
file.WriteLine(tab2 + "public static String GetColumnName (ColumnIdx column, bool delimitReservedWords = true)");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab3 + "int columnIdx = (int)column - 1;");
|
|
file.WriteLine(tab3 + "if (columnIdx < 0 || columnIdx >= columnCount) return String.Empty;");
|
|
file.WriteLine(tab3 + "String columnName = columns[columnIdx].Name;");
|
|
file.WriteLine(tab3 + "if (delimitReservedWords) columnName = DelimitReservedWord(columnName);");
|
|
file.WriteLine(tab3 + "return columnName;");
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(tab2 + "public static String GetColumnNameQual (ColumnIdx column, String tableAlias = \"\", bool braces = false)");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab3 + "String columnName = GetColumnName(column);");
|
|
file.WriteLine(tab3 + "if (!String.IsNullOrEmpty(columnName))");
|
|
file.WriteLine(tab3 + "{");
|
|
file.WriteLine(tab4 + "String tableName = StringUtil.EmptyOnNull(tableAlias);");
|
|
file.WriteLine(tab4 + "if (tableName.IsEmpty()) tableName = GetTableName(GetTableForColumn(column));");
|
|
file.WriteLine(tab4 + "columnName = tableName + (tableName.Length > 0 ? \".\" : \"\") + columnName;");
|
|
file.WriteLine(tab4 + "if (braces)");
|
|
file.WriteLine(tab5 + "columnName = \"(\" + columnName + \")\";");
|
|
file.WriteLine(tab3 + "}");
|
|
file.WriteLine(tab3 + "return columnName;");
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
|
|
|
// Reserved word methods.
|
|
file.WriteLine(tab2 + "// Reserved words.");
|
|
file.WriteLine(tab2 + "private static DbReservedWordDelim reservedWordDelim = DbReservedWordDelim.SquareBrackets;");
|
|
file.WriteLine(tab2 + "public static void SetReservedWordDelim (DbReservedWordDelim reservedWordDelim)");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab3 + classnameDefinition + ".reservedWordDelim = reservedWordDelim;");
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(tab2 + "public static bool IsReservedWord (String word)");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab3 + "if (String.IsNullOrEmpty(word)) return false;");
|
|
file.WriteLine(tab3 + "if (reservedWords.Contains(word, StringComparer.OrdinalIgnoreCase)) return true;");
|
|
file.WriteLine(tab3 + "return false;");
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(tab2 + "public static String DelimitReservedWord (String word)");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab3 + "return IsReservedWord(word) ? DelimitWord(word) : word;");
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(tab2 + "public static String DelimitWord (String word)");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab3 + "return DelimitWord(word, reservedWordDelim);");
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(tab2 + "public static String DelimitWord (String word, DbReservedWordDelim wordDelim)");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab3 + "switch (wordDelim)");
|
|
file.WriteLine(tab3 + "{");
|
|
file.WriteLine(tab4 + "case DbReservedWordDelim.None:");
|
|
file.WriteLine(tab5 + "break;");
|
|
file.WriteLine(tab4 + "case DbReservedWordDelim.DoubleQuotes:");
|
|
file.WriteLine(tab5 + "word = \"\\\"\" + word + \"\\\"\"; ");
|
|
file.WriteLine(tab5 + "break;");
|
|
file.WriteLine(tab4 + "case DbReservedWordDelim.SquareBrackets:");
|
|
file.WriteLine(tab4 + "default:");
|
|
file.WriteLine(tab5 + "word = \"[\" + word + \"]\"; ");
|
|
file.WriteLine(tab5 + "break;");
|
|
file.WriteLine(tab3 + "}");
|
|
file.WriteLine(tab3 + "return word;");
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
|
|
|
// Column information methods.
|
|
file.WriteLine(tab2 + "// Retrieve information about the specified Column.");
|
|
file.WriteLine(tab2 + "public static DbColumnDataType GetColDataType (ColumnIdx column)");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab3 + "int columnIdx = (int)column - 1;");
|
|
file.WriteLine(tab3 + "if (columnIdx < 0 || columnIdx >= columnCount) return DbColumnDataType.Unknown;");
|
|
file.WriteLine(tab3 + "return columns[columnIdx].DataType;");
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(tab2 + "public static short GetColNativeDataType (ColumnIdx column)");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab3 + "int columnIdx = (int)column - 1;");
|
|
file.WriteLine(tab3 + "if (columnIdx < 0 || columnIdx >= columnCount) return 0;");
|
|
file.WriteLine(tab3 + "return columns[columnIdx].NativeDataType;");
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(tab2 + "public static void SetMaxTextLen (ulong maxTextLen)");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab3 + classnameDefinition + ".maxTextLen = maxTextLen;");
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(tab2 + "public static bool IsColFmtText (ColumnIdx column)");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab3 + "int columnIdx = (int)column - 1;");
|
|
file.WriteLine(tab3 + "if (columnIdx < 0 || columnIdx >= columnCount) return false;");
|
|
file.WriteLine(tab3 + "return (columns[columnIdx].DataType == DbColumnDataType.VarChar);");
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(tab2 + "public static ulong GetColTextLen (ColumnIdx column)");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab3 + "int columnIdx = (int)column - 1;");
|
|
file.WriteLine(tab3 + "if (columnIdx < 0 || columnIdx >= columnCount) return 0;");
|
|
file.WriteLine(tab3 + "if (columns[columnIdx].DataType == DbColumnDataType.VarChar)");
|
|
file.WriteLine(tab3 + "{");
|
|
file.WriteLine(tab4 + "ulong textLen = columns[columnIdx].DataLen;");
|
|
file.WriteLine(tab4 + "if (maxTextLen > 0 && textLen > maxTextLen) textLen = maxTextLen;");
|
|
file.WriteLine(tab4 + "return textLen;");
|
|
file.WriteLine(tab3 + "}");
|
|
file.WriteLine(tab3 + "return 0;");
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(tab2 + "public static bool IsColFmtBool (ColumnIdx column)");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab3 + "int columnIdx = (int)column - 1;");
|
|
file.WriteLine(tab3 + "if (columnIdx < 0 || columnIdx >= columnCount) return false;");
|
|
file.WriteLine(tab3 + "return (columns[columnIdx].DataType == DbColumnDataType.Bit);");
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(tab2 + "public static bool IsColFmtNumeric (ColumnIdx column)");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab3 + "int columnIdx = (int)column - 1;");
|
|
file.WriteLine(tab3 + "if (columnIdx < 0 || columnIdx >= columnCount) return false;");
|
|
file.WriteLine(tab3 + "switch (columns[columnIdx].DataType)");
|
|
file.WriteLine(tab3 + "{");
|
|
file.WriteLine(tab4 + "case DbColumnDataType.TinyInt:");
|
|
file.WriteLine(tab4 + "case DbColumnDataType.SmallInt:");
|
|
file.WriteLine(tab4 + "case DbColumnDataType.Int:");
|
|
file.WriteLine(tab4 + "case DbColumnDataType.BigInt:");
|
|
file.WriteLine(tab4 + "case DbColumnDataType.Single:");
|
|
file.WriteLine(tab4 + "case DbColumnDataType.Double:");
|
|
file.WriteLine(tab4 + "case DbColumnDataType.Decimal:");
|
|
file.WriteLine(tab5 + "return true;");
|
|
file.WriteLine(tab3 + "}");
|
|
file.WriteLine(tab3 + "return false;");
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
|
|
|
// Table names.
|
|
file.WriteLine(tab2 + "// Table definitions.");
|
|
file.WriteLine(tab2 + "private class TableDfn");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab3 + "internal String Schema { get; set; }");
|
|
file.WriteLine(tab3 + "internal String Name { get; set; }");
|
|
file.WriteLine(tab3 + "internal TableDfn (String schema, String name)");
|
|
file.WriteLine(tab3 + "{");
|
|
file.WriteLine(tab4 + "this.Schema= schema;");
|
|
file.WriteLine(tab4 + "this.Name = name;");
|
|
file.WriteLine(tab3 + "}");
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(tab2 + "private static readonly TableDfn[] tables =");
|
|
file.WriteLine(tab2 + "{");
|
|
foreach (DbDfnTable tableDfn in tableDfns)
|
|
file.WriteLine(tab3 + "new TableDfn(\"" + tableDfn.Schema + "\",\"" + tableDfn.Name + "\"),");
|
|
file.WriteLine(tab2 + "};");
|
|
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
|
|
|
// Table Column definitions.
|
|
file.WriteLine(tab2 + "// Table column definitions.");
|
|
file.WriteLine(tab2 + "private class ColumnDfn");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab3 + "internal TableIdx TableIdx { get; set; }");
|
|
file.WriteLine(tab3 + "internal String Name { get; set; }");
|
|
file.WriteLine(tab3 + "internal DbColumnDataType DataType { get; set; }");
|
|
file.WriteLine(tab3 + "internal short NativeDataType { get; set; }");
|
|
file.WriteLine(tab3 + "internal bool IsIdentity { get; set; }");
|
|
file.WriteLine(tab3 + "internal ulong DataLen { get; set; }");
|
|
file.WriteLine(tab3 + "internal ColumnDfn (int tableIdx, String name, int dataType, short nativeDataType, bool isIdentity, ulong dataLen)");
|
|
file.WriteLine(tab3 + "{");
|
|
file.WriteLine(tab4 + "this.TableIdx = (TableIdx)tableIdx;");
|
|
file.WriteLine(tab4 + "this.Name = name;");
|
|
file.WriteLine(tab4 + "this.DataType = (DbColumnDataType)dataType;");
|
|
file.WriteLine(tab4 + "this.NativeDataType = nativeDataType;");
|
|
file.WriteLine(tab4 + "this.IsIdentity = isIdentity;");
|
|
file.WriteLine(tab4 + "this.DataLen = dataLen;");
|
|
file.WriteLine(tab3 + "}");
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(tab2 + "private static readonly ColumnDfn[] columns =");
|
|
file.WriteLine(tab2 + "{");
|
|
uint tableIdx = 0;
|
|
foreach (DbDfnTable tableDfn in tableDfns)
|
|
{
|
|
tableIdx++;
|
|
foreach (var columnDfn in tableDfn.Columns)
|
|
file.WriteLine(tab3 + "new ColumnDfn(" + tableIdx.ToString() + ",\"" + columnDfn.Name + "\"," + ((int)columnDfn.DataType).ToString() + "," + columnDfn.DataTypeNative.ToString() + "," + (columnDfn.IsIdentity ? "true" : "false") + "," + columnDfn.Size.ToString() + "),");
|
|
}
|
|
file.WriteLine(tab2 + "};");
|
|
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
|
|
|
// Reserved words.
|
|
file.WriteLine(tab2 + "// Reserved words.");
|
|
file.WriteLine(tab2 + "private static readonly List<String> reservedWords = new List<String>()");
|
|
file.WriteLine(tab2 + "{");
|
|
foreach (String reservedword in reservedWords)
|
|
file.WriteLine(tab3 + "\"" + reservedword + "\", ");
|
|
file.WriteLine(tab2 + "};");
|
|
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// T a b l e C l a s s
|
|
//-------------------------------------------------------------------
|
|
private void GenerateTableInterfaceClass(DbDfnTable tableDfn)
|
|
{
|
|
String className = tableDfn.Name + "_Db";
|
|
if (!StringUtil.IsEmpty(tableDfn.Schema) && !tableDfn.Schema.EqualsCI("dbo"))
|
|
{
|
|
className = config.Schema.SchemaNameCapitalisation.GetValueOrDefault(tableDfn.Schema, StringUtil.CapitaliseFirst(tableDfn.Schema)) + "_" + className;
|
|
}
|
|
List<String> primaryColumnNames = tableDfn.GetPrimaryColumnNames();
|
|
String identityColumnName = tableDfn.Columns.GetIdentityColumnName();
|
|
String identityColumnVariableTypeName = tableDfn.Columns.GetIdentityColumnVariableTypeName();
|
|
String identityColumnCastFromInt64 = (!identityColumnVariableTypeName.EqualsCI("Int64") && !identityColumnVariableTypeName.EqualsCI("long") ? "(" + identityColumnVariableTypeName + ")" : "");
|
|
|
|
// Class 'using's.
|
|
List<String> usingNamespaces = new List<string>(config.TableClass.Usings);
|
|
usingNamespaces.AddRange(new List<String>()
|
|
{
|
|
config.TableClass.Namespace_BaseClass,
|
|
"System",
|
|
"System.Collections.Generic",
|
|
"System.Data.Common",
|
|
config.DotNetVersion == DotNetVersion.Framework? "System.Data.Odbc" : "",
|
|
config.DotNetVersion == DotNetVersion.Core3 ? "Microsoft.Data.SqlClient" : "System.Data.SqlClient",
|
|
"System.Linq"
|
|
});
|
|
usingNamespaces.RemoveBlanks();
|
|
usingNamespaces.RemoveDuplicatesCI();
|
|
usingNamespaces.Sort();
|
|
|
|
// Alternative table names.
|
|
List<String> alternativeTableNames = new List<string>();
|
|
if (config.Schema.AlternativeTableNames.ContainsKey(tableDfn.Name))
|
|
alternativeTableNames.AddRange(config.Schema.AlternativeTableNames[tableDfn.Name]);
|
|
|
|
// List of columns to be ignored on update.
|
|
List<String> columnsIgnoredOnUpdate = new List<string>();
|
|
foreach (StringPair insertOnlyColumns in config.Schema.InsertOnlyColumns.FindAll(x => Regex.IsMatch(tableDfn.Name, x.Item1, RegexOptions.IgnoreCase)))
|
|
columnsIgnoredOnUpdate.AddRange(insertOnlyColumns.Item2.Split(','));
|
|
for (int i = 0; i < columnsIgnoredOnUpdate.Count; i++)
|
|
columnsIgnoredOnUpdate[i] = columnsIgnoredOnUpdate[i].Trim(' ');
|
|
|
|
String filePath = config.OutputDirectory + Path.DirectorySeparatorChar + className + ".cs";
|
|
using (StreamWriter file = new StreamWriter(filePath))
|
|
{
|
|
// Database definition file.
|
|
foreach (String usingNamespace in usingNamespaces)
|
|
file.WriteLine("using " + usingNamespace + ";");
|
|
file.WriteLine("");
|
|
file.WriteLine("//---------------------------------------------------------------------------");
|
|
file.WriteLine("// Code generated by Sarand Database Utilities " + DateTime.Now.Format("ddd d-MMM-yyyy HH:mm:ss"));
|
|
file.WriteLine("//---------------------------------------------------------------------------");
|
|
file.WriteLine("namespace " + config.TableClass.Namespace);
|
|
file.WriteLine("{");
|
|
file.WriteLine(tab1 + "internal class " + className + " : " + config.TableClass.BaseClass);
|
|
file.WriteLine(tab1 + "{");
|
|
file.WriteLine(tab2 + "//-------------------------------------------------------------------");
|
|
file.WriteLine(tab2 + "// Column definitions.");
|
|
file.WriteLine(tab2 + "public class ColumnsData");
|
|
file.WriteLine(tab2 + "{");
|
|
foreach (var columnDfn in tableDfn.Columns)
|
|
{
|
|
String columnDataClassName = "ColumnData" + GetColumnVariableTypeName(columnDfn) + (TreatColumnAsNullable(columnDfn) ? "Nullable" : "");
|
|
file.WriteLine(tab3 + "public " + columnDataClassName + " _" + columnDfn.Name + " { get; } = new " + columnDataClassName + "(\"" + columnDfn.Name + "\"" + (columnDfn.IsIdentity ? ", true" : "") + ");");
|
|
}
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
|
file.WriteLine(tab2 + "// Data members.");
|
|
file.WriteLine(tab2 + "protected static List<String> fields { get; } = new List<String>()");
|
|
file.WriteLine(tab2 + "{");
|
|
foreach (var columnDfn in tableDfn.Columns) file.WriteLine(tab3 + "\"" + columnDfn.Name + "\",");
|
|
file.WriteLine(tab2 + "};");
|
|
file.WriteLine(tab2 + "protected static List<String> fieldsId { get; } = new List<String>()");
|
|
file.WriteLine(tab2 + "{");
|
|
foreach (var columnDfn in tableDfn.Columns.FindAll(item => item.IsIdentity)) file.WriteLine(tab3 + "\"" + columnDfn.Name + "\",");
|
|
file.WriteLine(tab2 + "};");
|
|
file.WriteLine(tab2 + "protected static List<String> fieldsPrimary { get; } = new List<String>()");
|
|
file.WriteLine(tab2 + "{");
|
|
foreach (String columnName in primaryColumnNames) file.WriteLine(tab3 + "\"" + columnName + "\",");
|
|
file.WriteLine(tab2 + "};");
|
|
file.WriteLine(tab2 + "protected static List<String> fieldsNullable { get; } = new List<String>()");
|
|
file.WriteLine(tab2 + "{");
|
|
foreach (var columnDfn in tableDfn.Columns.FindAll(item => item.IsNullable)) file.WriteLine(tab3 + "\"" + columnDfn.Name + "\",");
|
|
file.WriteLine(tab2 + "};");
|
|
file.WriteLine(tab2 + "protected static List<String> fieldsIgnoreOnUpdate { get; } = new List<String>()");
|
|
file.WriteLine(tab2 + "{");
|
|
foreach (String columnName in columnsIgnoredOnUpdate) file.WriteLine(tab3 + "\"" + columnName + "\",");
|
|
file.WriteLine(tab2 + "};");
|
|
/*
|
|
file.WriteLine(tab2 + "protected static List<String> fieldsNonId { get; } = new List<String>()");
|
|
file.WriteLine(tab2 + "{");
|
|
foreach (var columnDfn in tableDfn.Columns.FindAll(item => !item.IsIdentity)) file.WriteLine(tab3 + "\"" + columnDfn.Name + "\",");
|
|
file.WriteLine(tab2 + "};");
|
|
*/
|
|
|
|
//-----------------------------------------------------------
|
|
// Construction.
|
|
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
|
file.WriteLine(tab2 + "// Construction.");
|
|
file.WriteLine(tab2 + "internal " + className + " (" + config.TableClass.ClassName_DatabaseInfo + " dbInfo" + (!config.TableClass.MandatoryConstructorDbInfo ? " = null" : "") + ") : base(dbInfo)");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab2 + "}");
|
|
|
|
//-----------------------------------------------------------
|
|
// Properties.
|
|
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
|
file.WriteLine(tab2 + "// Properties.");
|
|
file.WriteLine(tab2 + "public override String SchemaName { get; } = \"" + tableDfn.Schema + "\";");
|
|
if (alternativeTableNames.Count == 0)
|
|
file.WriteLine(tab2 + "public override String TableName { get; } = \"" + tableDfn.Name + "\";");
|
|
else
|
|
{
|
|
// Logic to handle alternative table names.
|
|
file.WriteLine(tab2 + "public override String TableName { get { return GetActualTableName(\"" + tableDfn.Name + "\"); } }");
|
|
file.WriteLine(tab2 + "public override List<String> AlternativeTableNames { get; } = new List<string>() { " + alternativeTableNames.Concat(", ", "\"", "\"") + " };");
|
|
}
|
|
file.WriteLine(tab2 + "public String TableNameFmt { get { return (!String.IsNullOrEmpty(SchemaName) ? \"[\" + SchemaName + \"].\" : \"\") + \"[\" + TableName + \"]\"; } }");
|
|
file.WriteLine(tab2 + "public static List<String> Fields { get { return new List<String>(fields); } }");
|
|
file.WriteLine(tab2 + "public static List<String> FieldsId { get { return new List<String>(fieldsId); } }");
|
|
file.WriteLine(tab2 + "public static List<String> FieldsNonId { get { return fields.FindAll(item => !fieldsId.ContainsCI(item)); } }");
|
|
file.WriteLine(tab2 + "// Columns.");
|
|
file.WriteLine(tab2 + "public ColumnsData Cols { get; } = new ColumnsData();");
|
|
foreach (var columnDfn in tableDfn.Columns)
|
|
file.WriteLine(tab2 + "public " + GetColumnVariableType(columnDfn) + (TreatColumnAsNullable(columnDfn) ? "?" : "") + " _" + columnDfn.Name + " { get { return Cols._" + columnDfn.Name + ".Value; } set { Cols._" + columnDfn.Name + ".Value = value; } }");
|
|
file.WriteLine(tab2 + "// Existing columns - confirmed on database if table exists.");
|
|
file.WriteLine(tab2 + "public List<String> ExistingColumnNames { get { return GetExistingColumnNames(Fields); } }");
|
|
file.WriteLine(tab2 + "public List<String> ExistingColumnNamesNonId { get { return GetExistingColumnNames(FieldsNonId); } }");
|
|
|
|
//-----------------------------------------------------------
|
|
// Population.
|
|
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
|
file.WriteLine(tab2 + "// Population.");
|
|
file.WriteLine(tab2 + "public override void PopulateFrom (DbCommand dbCommand, String tableAlias, String filter)");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab3 + "dbCommand.CommandText =");
|
|
file.WriteLine(tab4 + "\"SELECT \" + ExistingColumnNames.Concat(\", \", (!String.IsNullOrEmpty(tableAlias) ? tableAlias + \".\" : \"\") + \"[\", \"]\") + \" \" +");
|
|
file.WriteLine(tab4 + "\"FROM \" + TableNameFmt + (!String.IsNullOrEmpty(tableAlias) ? \" \" + tableAlias : \"\") + \" \" + ");
|
|
file.WriteLine(tab4 + "(!String.IsNullOrEmpty(filter) ? \"WHERE \" + filter : \"\");");
|
|
file.WriteLine(tab3 + "Log(GetType().Name + \".PopulateFrom\", dbCommand.CommandText);");
|
|
file.WriteLine(tab3 + "using (DbDataReader dbDataReader = dbCommand.ExecuteReader())");
|
|
file.WriteLine(tab3 + "{");
|
|
file.WriteLine(tab4 + "dbDataReader.Read();");
|
|
file.WriteLine(tab4 + "PopulateFrom(dbDataReader);");
|
|
file.WriteLine(tab3 + "}");
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(tab2 + "public override void PopulateFrom (DbDataReader dbDataReader)");
|
|
file.WriteLine(tab2 + "{");
|
|
foreach (var columnDfn in tableDfn.Columns)
|
|
file.WriteLine(tab3 + "_" + columnDfn.Name + " = GetField" + GetColumnGetFieldSuffix(columnDfn) + (TreatColumnAsNullable(columnDfn) ? "Nullable" : "") + "(dbDataReader, \"" + columnDfn.Name + "\", _" + columnDfn.Name + ");");
|
|
file.WriteLine(tab2 + "}");
|
|
|
|
//-----------------------------------------------------------
|
|
// Prepare Insert command.
|
|
// SQL:
|
|
// Parameters can be named.
|
|
// Multiple queries allowed - can append 'SELECT Scope_Identity();' to insert query.
|
|
// ODBC:
|
|
// Parameters identified as '?' and matched by position in parameter list.
|
|
// Single queries only. Use Max(Id) to retrieve identity value.
|
|
//-----------------------------------------------------------
|
|
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
|
file.WriteLine(tab2 + "// Insert command.");
|
|
file.WriteLine(tab2 + "public override bool ExecuteInsertCommand (DbCommand dbCommand)");
|
|
file.WriteLine(tab2 + "{");
|
|
file.WriteLine(tab3 + "List<String> columnNames = ExistingColumnNamesNonId;");
|
|
if (!String.IsNullOrEmpty(identityColumnName))
|
|
{
|
|
file.WriteLine(tab3 + "// Avoid insert if Identity field is already valid.");
|
|
file.WriteLine(tab3 + "if (_" + identityColumnName + " != 0) throw new Exception(\"Invalid for Insert - item already has a valid Id\"); ");
|
|
}
|
|
file.WriteLine(tab3 + "// Construct query.");
|
|
file.WriteLine(tab3 + "String query =");
|
|
file.WriteLine(tab4 + "\"INSERT INTO \" + TableNameFmt + \" \" +");
|
|
file.WriteLine(tab4 + "\"(\"+columnNames.Concat(\",\",\"[\",\"]\")+\") \";");
|
|
if (!String.IsNullOrEmpty(identityColumnName))
|
|
file.WriteLine(tab3 + "query += \"Output Inserted." + identityColumnName + " \";");
|
|
List<String> columnsValuesToInsertSql = new List<String>();
|
|
foreach (var columnDfn in tableDfn.Columns.Where(col => !col.IsIdentity))
|
|
columnsValuesToInsertSql.Add("@" + columnDfn.Name);
|
|
file.WriteLine(tab3 + "if (dbCommand is SqlCommand)");
|
|
file.WriteLine(tab4 + "query += \"VALUES (\" + columnNames.Concat(\",\", \"@\", \"\") + \") \";");
|
|
file.WriteLine(tab3 + "else query += \"VALUES (\" + " + (config.SarandCommonVersion == SarandCommonVersion.VS2019 ? "StringListUtil" : "StringList") + ".CreateList(\"?\", columnNames.Count).Concat(\",\") + \") \";");
|
|
if (!String.IsNullOrEmpty(identityColumnName) && config.DbmsOutput == Dbms.SQL)
|
|
file.WriteLine(tab3 + "query += SELECT Scope_Identity();"); // NB @@Identity for Access.
|
|
file.WriteLine(tab3 + "dbCommand.CommandText = query;");
|
|
file.WriteLine(tab3 + "Log(GetType().Name + \".ExecuteInsertCommand\", dbCommand.CommandText);");
|
|
file.WriteLine(tab3 + "// Populate parameters.");
|
|
file.WriteLine(tab3 + "dbCommand.Parameters.Clear();");
|
|
foreach (var columnDfn in tableDfn.Columns.Where(col => !col.IsIdentity))
|
|
file.WriteLine(tab3 + "if (columnNames.ContainsCI(\"" + columnDfn.Name + "\")) AddCommandParameter(dbCommand, \"@" + columnDfn.Name + "\", _" + columnDfn.Name + ");");
|
|
file.WriteLine(tab3 + "// Execute insert command.");
|
|
file.WriteLine(tab3 + "bool commandSuccess = false;");
|
|
if (config.DbmsOutput == Dbms.SQL)
|
|
{
|
|
if (!String.IsNullOrEmpty(identityColumnName))
|
|
{
|
|
// Execute single command to insert and query 'Scope_Identity' to retrieve Identity value.
|
|
file.WriteLine(tab3 + "_" + identityColumnName + " = " + identityColumnCastFromInt64 + "Convert.ToInt64(dbCommand.ExecuteScalar());");
|
|
file.WriteLine(tab3 + "commandSuccess = (_" + identityColumnName + " > 0);");
|
|
}
|
|
else
|
|
{
|
|
// Execute query and retrieve number of records (may return -1).
|
|
file.WriteLine(tab3 + "int executeNonQuery = dbCommand.ExecuteNonQuery();");
|
|
file.WriteLine(tab3 + "commandSuccess = true;");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Execute query.
|
|
file.WriteLine(tab3 + "int executeNonQuery = dbCommand.ExecuteNonQuery();");
|
|
file.WriteLine(tab3 + "if (executeNonQuery == 1)"); // No of records inserted? Returns -1?
|
|
file.WriteLine(tab3 + "{");
|
|
if (!String.IsNullOrEmpty(identityColumnName))
|
|
{
|
|
// Retrieve Identity value.
|
|
file.WriteLine(tab4 + "dbCommand.CommandText = \"SELECT Max(" + identityColumnName + ") FROM \" + TableNameFmt + \";\";");
|
|
file.WriteLine(tab4 + "_" + identityColumnName + " = " + identityColumnCastFromInt64 + "Convert.ToInt64(dbCommand.ExecuteScalar());");
|
|
file.WriteLine(tab4 + "commandSuccess = (_" + identityColumnName + " > 0);");
|
|
}
|
|
else
|
|
{
|
|
file.WriteLine(tab4 + "commandSuccess = true;");
|
|
}
|
|
file.WriteLine(tab3 + "}");
|
|
}
|
|
file.WriteLine(tab3 + "return commandSuccess;");
|
|
file.WriteLine(tab2 + "}");
|
|
|
|
//-----------------------------------------------------------
|
|
// Prepare Update command.
|
|
// Filter: Primary index values.
|
|
// Update: Non-primary index values.
|
|
// SQL:
|
|
// Parameters can be named.
|
|
// ODBC:
|
|
// Parameters identified as '?' and matched by position in parameter list.
|
|
// Single queries only. Use Max(Id) to retrieve identity value.
|
|
//-----------------------------------------------------------
|
|
// Construct update command.
|
|
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
|
file.WriteLine(tab2 + "// Update command.");
|
|
file.WriteLine(tab2 + "public override bool ExecuteUpdateCommand (DbCommand dbCommand)");
|
|
file.WriteLine(tab2 + "{");
|
|
if (!String.IsNullOrEmpty(identityColumnName))
|
|
{
|
|
file.WriteLine(tab3 + "// Avoid update if Identity field isn't valid.");
|
|
file.WriteLine(tab3 + "if (_" + identityColumnName + " == 0) throw new Exception(\"Invalid for Update - item has an invalid Id\"); ");
|
|
}
|
|
file.WriteLine(tab3 + "// Columns to update.");
|
|
file.WriteLine(tab3 + "List<String> columnNames = ExistingColumnNamesNonId.Where(item => !fieldsPrimary.ContainsCI(item) && !fieldsIgnoreOnUpdate.ContainsCI(item)).ToList();");
|
|
file.WriteLine(tab3 + "// Construct query.");
|
|
file.WriteLine(tab3 + "String query = \"UPDATE \" + TableNameFmt + \" SET \";");
|
|
List<String> columnsValuesToUpdate = new List<String>();
|
|
List<String> columnsValuesToUpdateSql = new List<String>();
|
|
foreach (var columnDfn in tableDfn.Columns)
|
|
{
|
|
if (primaryColumnNames.Any(col => col.EqualsCI(columnDfn.Name))) continue;
|
|
if (columnsIgnoredOnUpdate.Any(col => col.EqualsCI(columnDfn.Name))) continue;
|
|
// Delimit reserved column names.
|
|
String columnNameSql = columnDfn.Name;
|
|
if (reservedWords.ToList().ContainsCI(columnNameSql))
|
|
columnNameSql = "[" + columnNameSql + "]";
|
|
columnsValuesToUpdate.Add(columnDfn.Name + "=?");
|
|
columnsValuesToUpdateSql.Add(columnNameSql + "=@" + columnDfn.Name);
|
|
}
|
|
//-----------------------------------------------------------
|
|
// SQL Update.
|
|
file.WriteLine(tab3 + "if (dbCommand is SqlCommand)");
|
|
file.WriteLine(tab3 + "{");
|
|
file.WriteLine(tab4 + "query += StringPairList.CreateFrom(columnNames.Bracket(\"[\",\"]\"),columnNames).Concat(\"=@\").Concat(\", \") + \" \";");
|
|
List<String> whereFilterSql = new List<string>();
|
|
foreach (var primaryColumnName in primaryColumnNames)
|
|
whereFilterSql.Add(primaryColumnName + "=@" + primaryColumnName);
|
|
file.WriteLine(tab4 + "query += \"WHERE " + whereFilterSql.Concat(" AND ") + ";\";");
|
|
file.WriteLine(tab3 + "}");
|
|
//-----------------------------------------------------------
|
|
// Non-SQL Update.
|
|
file.WriteLine(tab3 + "else");
|
|
file.WriteLine(tab3 + "{");
|
|
file.WriteLine(tab4 + "query += columnNames.Concat(\", \", \"\", \"=?\") + \" \";");
|
|
List<String> whereFilterNonSql = new List<string>();
|
|
foreach (var primaryColumnName in primaryColumnNames)
|
|
whereFilterNonSql.Add(primaryColumnName + "=?");
|
|
file.WriteLine(tab4 + "query += \"WHERE " + whereFilterNonSql.Concat(" AND ") + ";\";");
|
|
file.WriteLine(tab3 + "}");
|
|
//-----------------------------------------------------------
|
|
// Populate parameters and execute update command.
|
|
file.WriteLine(tab3 + "dbCommand.CommandText = query;");
|
|
file.WriteLine(tab3 + "Log(GetType().Name + \".ExecuteUpdateCommand\", dbCommand.CommandText);");
|
|
file.WriteLine(tab3 + "// Populate parameters.");
|
|
file.WriteLine(tab3 + "dbCommand.Parameters.Clear();");
|
|
foreach (var columnDfn in tableDfn.Columns.FindAll(item => !primaryColumnNames.Contains(item.Name) && !columnsIgnoredOnUpdate.Contains(item.Name)))
|
|
file.WriteLine(tab3 + "if (columnNames.ContainsCI(\"" + columnDfn.Name + "\")) AddCommandParameter(dbCommand, \"@" + columnDfn.Name + "\", _" + columnDfn.Name + ");");
|
|
foreach (var primaryColumnName in primaryColumnNames)
|
|
file.WriteLine(tab3 + "AddCommandParameter(dbCommand, \"@" + primaryColumnName + "\", _" + primaryColumnName + ");");
|
|
file.WriteLine(tab3 + "int executeNonQueryResult = dbCommand.ExecuteNonQuery();");
|
|
file.WriteLine(tab3 + "return (executeNonQueryResult == 1);");
|
|
file.WriteLine(tab2 + "}");
|
|
file.WriteLine(crlf + tab2 + "//-------------------------------------------------------------------");
|
|
|
|
// Close class.
|
|
file.WriteLine(tab1 + "}");
|
|
file.WriteLine("}");
|
|
//file.Close(); - Unecessary as the object will be disposed at the end of the 'using' block.
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
}
|
|
//=======================================================================
|
|
}
|