From c01aa9441b4774eba4dc842641a4528b33c18cd9 Mon Sep 17 00:00:00 2001 From: Andy Howard Date: Sat, 29 Nov 2025 17:03:24 +0000 Subject: [PATCH] BusinessMgr 3.0.2.1 --- .../Dbas/Data/SacsDatabaseOdbc.cs | 102 ++++++++++-------- 1 file changed, 56 insertions(+), 46 deletions(-) diff --git a/SacsStandardDbas/Dbas/Data/SacsDatabaseOdbc.cs b/SacsStandardDbas/Dbas/Data/SacsDatabaseOdbc.cs index c0ab582..46b4f28 100644 --- a/SacsStandardDbas/Dbas/Data/SacsDatabaseOdbc.cs +++ b/SacsStandardDbas/Dbas/Data/SacsDatabaseOdbc.cs @@ -1,18 +1,18 @@ -using System; +using Microsoft.Data.SqlClient; +using Sarand.Net.Standard.Base.App; +using Sarand.Net.Standard.Base.Bus; +using Sarand.Net.Standard.Base.Core; +using Sarand.Net.Standard.Base.Dbas; +using Sarand.Net.Standard.Base.Security; +using Sarand.Net.Standard.Base.Utils; +using Sarand.Net.Standard.Dbas.Base; +using System; using System.Collections.Generic; using System.Data; using System.Data.Common; using System.Data.Odbc; -using Microsoft.Data.SqlClient; -using System.Linq; -using Sarand.Net.Standard.Base.App; -using Sarand.Net.Standard.Base.Core; -using Sarand.Net.Standard.Base.Bus; -using Sarand.Net.Standard.Base.Dbas; -using Sarand.Net.Standard.Dbas.Base; -using Sarand.Net.Standard.Base.Utils; using System.Diagnostics; -using Sarand.Net.Standard.Base.Security; +using System.Linq; namespace Sarand.Net.Standard.Dbas.Data { @@ -75,10 +75,10 @@ namespace Sarand.Net.Standard.Dbas.Data PopulateNextIdTableDfn(); // Next Id database definitions. - String colObject = NextIdTable + "." + NextIdColumn_Object; - String colNextId = NextIdTable + "." + NextIdColumn_NextId; + String colObject = $"{NextIdTable}.{NextIdColumn_Object}"; + String colNextId = $"{NextIdTable}.{NextIdColumn_NextId}"; String colAliasNextId = "NxtId"; - String filter = "(" + colObject + ")='" + objectName + "'"; + String filter = $"({colObject})='{objectName}'"; bool hasCreateCols = (nextIdTableDfn.HasColumnByName(DbCol_CreateOn) && nextIdTableDfn.HasColumnByName(DbCol_CreateBy)); bool hasUpdateCols = (nextIdTableDfn.HasColumnByName(DbCol_UpdateOn) && nextIdTableDfn.HasColumnByName(DbCol_UpdateBy)); @@ -102,7 +102,7 @@ namespace Sarand.Net.Standard.Dbas.Data updateColumnValues.Add(DbCol_UpdateOn, DbQuery.FormatDateTimeForCondition(DateTime.Now)); updateColumnValues.Add(DbCol_UpdateBy, SysId.IsValid(dbUpdateInfo.UserId) ? SysId.ToString(dbUpdateInfo.UserId) : "0"); } - String updateQry = "Update " + NextIdTable + " Set " + updateColumnValues.Concat("=").Concat(", ") + " Where " + filter; + String updateQry = $"Update {NextIdTable} Set {updateColumnValues.Concat("=").Concat(", ")} Where {filter}"; //SaLogger.Debug($"{SysUtil.Fn} Update query: {updateQry}"); using (var dbConnection = CreateConnection()) using (var dbCommand = dbConnection.CreateCommand()) @@ -122,7 +122,7 @@ namespace Sarand.Net.Standard.Dbas.Data // Construct query to store Next Id value. List insertColumnValues = new List(); - insertColumnValues.Add(NextIdColumn_Object, "'" + DbQuery.FormatForCondition(objectName) + "'"); + insertColumnValues.Add(NextIdColumn_Object, $"'{DbQuery.FormatForCondition(objectName)}'"); insertColumnValues.Add(NextIdColumn_NextId, (nextIdValue + 1).ToString()); if (hasCreateCols) { @@ -134,7 +134,7 @@ namespace Sarand.Net.Standard.Dbas.Data insertColumnValues.Add(DbCol_UpdateOn, DbQuery.FormatDateTimeForCondition(DateTime.Now)); insertColumnValues.Add(DbCol_UpdateBy, SysId.IsValid(dbUpdateInfo.UserId) ? SysId.ToString(dbUpdateInfo.UserId) : "0"); } - String insertQry = "Insert Into " + NextIdTable + " (" + insertColumnValues.GetValues(StringPair.Value.Value1).Concat(",") + ") Values (" + insertColumnValues.GetValues(StringPair.Value.Value2).Concat(",") + ")"; + String insertQry = $"Insert Into {NextIdTable} ({insertColumnValues.GetValues(StringPair.Value.Value1).Concat(",")}) Values ({insertColumnValues.GetValues(StringPair.Value.Value2).Concat(",")})"; SaLogger.Debug($"{SysUtil.Fn} Insert query: {insertQry}"); using (var dbConnection = CreateConnection()) using (var dbCommand = dbConnection.CreateCommand()) @@ -150,7 +150,7 @@ namespace Sarand.Net.Standard.Dbas.Data } public override int GetNextIdFromTable(String objectName, String idColumn = "Id") { - DataValue maxId = GetRowValue(SaSecurityDbDfn.DelimitReservedWord(objectName), "Max(" + idColumn + ")", ""); + DataValue maxId = GetRowValue(SaSecurityDbDfn.DelimitReservedWord(objectName), $"Max({idColumn})", ""); if (maxId != null && maxId.GetDataType() != DataValue.DataType.Unknown) return Math.Max(0, (int)maxId.AsLong()) + 1; return 1; @@ -176,7 +176,7 @@ namespace Sarand.Net.Standard.Dbas.Data public override DbResultSet ExecuteQuery(String query) { ClearErrorState(); - Log(SysUtil.Fn, "Query: " + query, SaMessageLevel.Debug); + Log(SysUtil.Fn, $"Query: {query}", SaMessageLevel.Debug); try { return DbResultSet_DataReader.ExecuteQuery(this, query); @@ -193,7 +193,7 @@ namespace Sarand.Net.Standard.Dbas.Data public override int ExecuteNonQuery(string query) { ClearErrorState(); - Log(SysUtil.Fn, "Query: " + query, SaMessageLevel.Debug); + Log(SysUtil.Fn, $"Query: {query}", SaMessageLevel.Debug); using (var dbConnection = CreateConnection()) using (var dbCommand = dbConnection.CreateCommand()) { @@ -218,10 +218,8 @@ namespace Sarand.Net.Standard.Dbas.Data { ClearErrorState(); String query = - "INSERT INTO " + tableName + " " + - "(" + columnNameValues.GetValues(StringPair.Value.Value1).Concat(", ") + ") " + - "VALUES (" + columnNameValues.GetValues(StringPair.Value.Value2).Concat(", ") + ")"; - Log(SysUtil.Fn, "Query: " + query, SaMessageLevel.Debug); + $"INSERT INTO {tableName} ({columnNameValues.GetValues(StringPair.Value.Value1).Concat(", ")}) VALUES ({columnNameValues.GetValues(StringPair.Value.Value2).Concat(", ")})"; + Log(SysUtil.Fn, $"Query: {query}", SaMessageLevel.Debug); using (var dbConnection = CreateConnection()) using (var dbCommand = dbConnection.CreateCommand()) { @@ -245,12 +243,10 @@ namespace Sarand.Net.Standard.Dbas.Data public override int ExecuteUpdate(String tableName, List columnNameValues, String filter) { ClearErrorState(); - String query = - "UPDATE " + tableName + " " + - "SET " + columnNameValues.Concat("=").Concat(", "); - if (!StringUtil.IsEmpty(filter)) - query += (String)" WHERE " + filter; - Log(SysUtil.Fn, "Query: " + query, SaMessageLevel.Debug); + String query = $"UPDATE {tableName} SET {columnNameValues.Concat("=").Concat(", ")}"; + if (!StringUtil.IsBlank(filter)) + query += $" WHERE {filter}"; + Log(SysUtil.Fn, $"Query: {query}", SaMessageLevel.Debug); using (var dbConnection = CreateConnection()) using (var dbCommand = dbConnection.CreateCommand()) { @@ -274,10 +270,10 @@ namespace Sarand.Net.Standard.Dbas.Data public override int ExecuteDelete(String tableName, String filter) { ClearErrorState(); - String query = "DELETE FROM " + tableName; - if (!StringUtil.IsEmpty(filter)) - query += " WHERE " + filter; - Log(SysUtil.Fn, "Query: " + query, SaMessageLevel.Debug); + String query = $"DELETE FROM {tableName}"; + if (!StringUtil.IsBlank(filter)) + query += $" WHERE {filter}"; + Log(SysUtil.Fn, $"Query: {query}", SaMessageLevel.Debug); using (var dbConnection = CreateConnection()) using (var dbCommand = dbConnection.CreateCommand()) { @@ -305,7 +301,7 @@ namespace Sarand.Net.Standard.Dbas.Data try { String colAlias = "DataValue"; - String query = "SELECT " + columnName + " '" + colAlias + "' FROM " + tableName + (!StringUtil.IsEmpty(filter) ? " WHERE " + filter : ""); + String query = $"SELECT {columnName} '{colAlias}' FROM {tableName}{(!StringUtil.IsBlank(filter) ? $" WHERE {filter}" : "")}"; using (DbResultSet dbResultSet = DbResultSet_DataReader.ExecuteQuery(this, query)) { if (dbResultSet.NextRecord()) @@ -316,7 +312,7 @@ namespace Sarand.Net.Standard.Dbas.Data } catch (Exception exc) { - SaLogger.Error($"{SysUtil.Fn} {ExceptionUtil.GetLogMessage(exc)}\n\tTable: {tableName}. Column: {columnName}. Filter: " + (!StringUtil.IsEmpty(filter) ? filter : ""), true); + SaLogger.Error($"{SysUtil.Fn} {ExceptionUtil.GetLogMessage(exc)}\n\tTable: {tableName}. Column: {columnName}. Filter: {(!StringUtil.IsBlank(filter) ? filter : "")}", true); SetErrorState(exc.Message); } return null; @@ -344,7 +340,7 @@ namespace Sarand.Net.Standard.Dbas.Data fn = "MIN"; else if (getValueType == DbGetValueType.eDbValueMax) fn = "MAX"; - return GetRowValue(tableName, fn + "(" + columnName + ")", filter); + return GetRowValue(tableName, $"{fn}({columnName})", filter); } //------------------------------------------------------------------- @@ -352,8 +348,18 @@ namespace Sarand.Net.Standard.Dbas.Data //------------------------------------------------------------------- // NB Always use ODBC connection for querying schema. // eg. SQL Connection GetSchema('Indices') doesn't return index columns. + public override HashSet GetTableNames(bool refresh = false) { + // Nov25 AH Was querying just table properties (not columns/indices) if definitions + // not previously fully populated (in GetTableDfns()) but this resulted in repeated + // querying of table properties, hence get full details immediately. + GetTableDfns(); + lock (tableDfns) + { + return tableDfns.Values.GetNames().ToHashSet(StringComparer.InvariantCultureIgnoreCase); + } + /* lock (tableDfns) { // Only populate table names if not previously done. @@ -368,7 +374,9 @@ namespace Sarand.Net.Standard.Dbas.Data } return tableDfns.Values.GetNames().ToHashSet(StringComparer.InvariantCultureIgnoreCase); } + */ } + public override List GetTableDfns(bool refresh = false) { lock (tableDfns) @@ -401,6 +409,7 @@ namespace Sarand.Net.Standard.Dbas.Data return new List(tableDfns.Values); } } + public void ClearTableDfns() { lock (tableDfns) @@ -409,6 +418,7 @@ namespace Sarand.Net.Standard.Dbas.Data tableDfnsPopulated = false; } } + public override DbDfnTable GetTableDfn(String tableName, bool refresh = false) { lock (tableDfns) @@ -418,7 +428,7 @@ namespace Sarand.Net.Standard.Dbas.Data // Remove current table definition. tableDfns.Remove(tableName); } - // Only populate the specified table if required. + // Only populate the specified table. DbDfnTable table = tableDfns.GetValueOrDefault(tableName); if (table == null || !table.HasColumns()) { @@ -443,7 +453,7 @@ namespace Sarand.Net.Standard.Dbas.Data private static List GetTableDefinitions(DbConnection dbConnection, String tableNameRestriction = null) { List tables = new List(); - if (SacsSystem.DebugMode) SaLogger.Debug($"{SysUtil.Fn} Database: {dbConnection.Database}." + (!StringUtil.IsEmpty(tableNameRestriction) ? $" Table: {tableNameRestriction}." : "")); + if (SacsSystem.DebugMode) SaLogger.Debug($"{SysUtil.Fn} Database: {dbConnection.Database}.{(!StringUtil.IsEmpty(tableNameRestriction) ? $" Table: {tableNameRestriction}." : "")}"); String[] restrictions = new String[] { null, null, tableNameRestriction }; // database, owner, table name, type using (DataTable tableSchema = dbConnection.GetSchema(OdbcMetaDataCollectionNames.Tables, restrictions)) { @@ -570,7 +580,7 @@ namespace Sarand.Net.Standard.Dbas.Data { String colName = column.ColumnName; String value = row[colName].ToString(); - //if (columnName.EqualsCI("CreateOn")) SaLogger.Debug(GetType().Name+".PopulateTableColumns Schema column name: " + colName + " [" + value + "]"); + //if (columnName.EqualsCI("CreateOn")) SaLogger.Debug($"{GetType().Name}.PopulateTableColumns Schema column name: {colName} [{value}]"); if (colName.EqualsCI("TABLE_CAT") || colName.EqualsCI("TABLE_CATALOG") || colName.EqualsCI("TABLE_QUALIFIER") || colName.EqualsCI("QualifierName")) database = value; else if (colName.EqualsCI("TABLE_SCHEM") || colName.EqualsCI("TABLE_SCHEMA") || colName.EqualsCI("TABLE_OWNER") || colName.EqualsCI("OwnerName")) @@ -654,7 +664,7 @@ namespace Sarand.Net.Standard.Dbas.Data } if (!StringUtil.IsEmpty(columnName)) { - //SaLogger.Debug(GetType().Name+".PopulateTableColumns Database=" + database + ", Schema=" + schema + ", Table=" + tableName + ", Column=" + columnName); + //SaLogger.Debug($"{GetType().Name}.PopulateTableColumns Database={database}, Schema={schema}, Table={tableName}, Column={columnName}"); DbDfnColumn column = new DbDfnColumn(schema, tableName, ++columnPos, columnName); column.DataTypeNative = nativeDataType; column.DataTypeNameNative = nativeDataTypeName; @@ -678,7 +688,7 @@ namespace Sarand.Net.Standard.Dbas.Data // Retrieve additional information via SqlDataReader. using (SqlCommand sqlCommand = sqlConnection.CreateCommand()) { - sqlCommand.CommandText = "Select Top 1 * From [" + table.Name + "]"; + sqlCommand.CommandText = $"Select Top 1 * From [{table.Name}]"; using (SqlDataReader sqlDataReader = sqlCommand.ExecuteReader(CommandBehavior.SchemaOnly)) using (DataTable dataTable = sqlDataReader.GetSchemaTable()) { @@ -691,7 +701,7 @@ namespace Sarand.Net.Standard.Dbas.Data String value = row[col].ToString(); if (col.ColumnName.EqualsCI("ColumnName")) columnName = value; else if (col.ColumnName.EqualsCI("IsIdentity")) isIdentity = value.ToBool(); - //if (columnName.EqualsCI("CreateOn")) SaLogger.Debug(GetType().Name+".PopulateTableColumns Column name: " + col.ColumnName + " [" + value + "]"); + //if (columnName.EqualsCI("CreateOn")) SaLogger.Debug($"{GetType().Name}.PopulateTableColumns Column name: {col.ColumnName} [{value}]"); } DbDfnColumn columnDfn = table.Columns.GetColumnByName(columnName); if (columnDfn != null) @@ -800,7 +810,7 @@ namespace Sarand.Net.Standard.Dbas.Data else if (colName.EqualsCI("FILTER_CONDITION") || colName.EqualsCI("FILTER")) filterCondition = value; //else SaLogger.Debug(GetType().Name+".PopulateTableIndices Unrecognised Schema column name: "+colName); - //SaLogger.Debug(GetType().Name+".PopulateTableIndices Column name: " + colName+", Value="+value); + //SaLogger.Debug($"{GetType().Name}.PopulateTableIndices Column name: {colName}, Value={value}"); } //------------------------------------------------------- @@ -837,14 +847,14 @@ namespace Sarand.Net.Standard.Dbas.Data { String colName = column.ColumnName; String value = row[colName].ToString(); - SaLogger.Debug(debugIndex + " Column: " + colName + ". Value: " + value); + SaLogger.Debug($"{debugIndex} Column: {colName}. Value: {value}"); } } //------------------------------------------------------- if (!StringUtil.IsEmpty(indexName)) { - //SaLogger.Debug(GetType().Name+".PopulateTableIndices Database=" + database + ", Schema=" + schema + ", Table=" + tableName + ", Index="+indexName+", Column=" + columnName); + //SaLogger.Debug($"{GetType().Name}.PopulateTableIndices Database={database}, Schema={schema}, Table={tableName}, Index={indexName}, Column={columnName}"); // Retrieve index or populate if not found. DbDfnIndex index = table.GetIndexByName(indexName); if (index == null) @@ -890,7 +900,7 @@ namespace Sarand.Net.Standard.Dbas.Data String value = row[colName].ToString(); String constraintCatalog, constraintSchema, constraintName, tableCatalog, tableSchema, tableName, columnName, ordinalPosition, keyType, indexName; #if DEBUG - //SaLogger.Trace(fn+" Column name=" + colName); + //SaLogger.Trace($"{SysUtil.Fn} Column name={colName}"); #endif if (colName.EqualsCI("constraint_catalog")) constraintCatalog = value;