From 966204d643fb5ecd2a5e21475f7e94643927262d Mon Sep 17 00:00:00 2001 From: Andy Howard Date: Wed, 16 Feb 2022 11:18:53 +0000 Subject: [PATCH] Saxonite v1.2.3 --- SaCommonVS.sln | 6 - .../Base/Helpers/SacsRandomHelper_Tester.cs | 86 ++++++ .../Base/Bus/SacsHierarchyItem.cs | 65 ++-- .../Base/Core/DisposableCollection.cs | 25 +- .../Base/Core/SacsQueueDictionary.cs | 115 +++++++ SacsStandardBase/Base/Dbas/OdbcUtil.cs | 2 +- .../Base/Helpers/SacsRandomHelper.cs | 17 +- SacsStandardBase/Base/Utils/DictionaryUtil.cs | 35 ++- SacsStandardBase/Base/Utils/ExceptionUtil.cs | 25 +- SacsStandardBase/Base/Utils/StringListUtil.cs | 8 +- .../Dbas/Data/SacsDatabaseOdbc.cs | 291 +++++++++--------- 11 files changed, 478 insertions(+), 197 deletions(-) create mode 100644 SacsCoreUnitTests/Standard/Base/Helpers/SacsRandomHelper_Tester.cs create mode 100644 SacsStandardBase/Base/Core/SacsQueueDictionary.cs diff --git a/SaCommonVS.sln b/SaCommonVS.sln index 100e7c3..90d5ef7 100644 --- a/SaCommonVS.sln +++ b/SaCommonVS.sln @@ -20,8 +20,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution files", "Solution EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SacsStandardAccounts", "SacsStandardAccounts\SacsStandardAccounts.csproj", "{C62999E2-1947-4EB7-82D2-A0EDB67D2F10}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SaBusMgrCoreProcs", "..\..\BusinessMgr\Workspace\SaBusMgrCoreProcs\SaBusMgrCoreProcs.csproj", "{452FC874-81D6-4858-A6F4-0337AA656D23}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -52,10 +50,6 @@ Global {C62999E2-1947-4EB7-82D2-A0EDB67D2F10}.Debug|Any CPU.Build.0 = Debug|Any CPU {C62999E2-1947-4EB7-82D2-A0EDB67D2F10}.Release|Any CPU.ActiveCfg = Release|Any CPU {C62999E2-1947-4EB7-82D2-A0EDB67D2F10}.Release|Any CPU.Build.0 = Release|Any CPU - {452FC874-81D6-4858-A6F4-0337AA656D23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {452FC874-81D6-4858-A6F4-0337AA656D23}.Debug|Any CPU.Build.0 = Debug|Any CPU - {452FC874-81D6-4858-A6F4-0337AA656D23}.Release|Any CPU.ActiveCfg = Release|Any CPU - {452FC874-81D6-4858-A6F4-0337AA656D23}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/SacsCoreUnitTests/Standard/Base/Helpers/SacsRandomHelper_Tester.cs b/SacsCoreUnitTests/Standard/Base/Helpers/SacsRandomHelper_Tester.cs new file mode 100644 index 0000000..a91f0d6 --- /dev/null +++ b/SacsCoreUnitTests/Standard/Base/Helpers/SacsRandomHelper_Tester.cs @@ -0,0 +1,86 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Sarand.Net.Standard.Base.Helpers; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; + +namespace Sacs.UnitTests.Net.Standard.Base.Helpers +{ + //======================================================================= + [TestClass] + public class SacsRandomHelper_Tester + { + //------------------------------------------------------------------- + // Random Helper. + //------------------------------------------------------------------- + // Fill byte array. + [TestMethod] + public void Fill_ByteArray() + { + int dataLength = 10; + byte[] data = new byte[dataLength]; + Assert.IsNotNull(data); + + // Initial values should be zero. + for (int i = 0; i < dataLength; i++) + Assert.AreEqual(0, data[i]); + + SacsRandomHelper.Fill(data); + + // Sum of data values should no longer be zero. + int total = 0; + for (int i = 0; i < dataLength; i++) + total += data[i]; + Assert.AreNotEqual(0, total); + + } + + //------------------------------------------------------------------- + [TestMethod] + public void GetInt32_ToExclusive() + { + for (int i = 1; i < 1000; i++) + { + int value = SacsRandomHelper.GetInt32(i); + Assert.IsTrue(value >= 0); + Assert.IsTrue(value < i); + } + } + + //------------------------------------------------------------------- + [TestMethod] + public void GetInt32_FromInclusive_ToExclusive() + { + for (int i = -100; i < 101; i++) + { + for (int j = i + 1; j < i + 100; j++) + { + int value = SacsRandomHelper.GetInt32(i, j); + //Debug.WriteLine("Value: "+value); + Assert.IsTrue(value >= i); + Assert.IsTrue(value < j); + } + } + } + + //------------------------------------------------------------------- + [TestMethod] + public void GetInt32_getRandomLengthNumber() + { + for (ushort i = 1; i < 13; i++) + { + for (int j = 0; j < 10; j++) + { + String value = SacsRandomHelper.getRandomLengthNumber(i); + //Debug.WriteLine("Value: " + value); + Assert.IsTrue(value.Length > 0); + Assert.IsTrue(value.Length < i + 1); + } + } + } + + //------------------------------------------------------------------- + } + //======================================================================= +} diff --git a/SacsStandardBase/Base/Bus/SacsHierarchyItem.cs b/SacsStandardBase/Base/Bus/SacsHierarchyItem.cs index c2a9491..1143f6f 100644 --- a/SacsStandardBase/Base/Bus/SacsHierarchyItem.cs +++ b/SacsStandardBase/Base/Bus/SacsHierarchyItem.cs @@ -77,12 +77,12 @@ namespace Sarand.Net.Standard.Base.Bus } } /// Get flag value - position 1 - 16 - public bool GetFlag (Byte flagPos) + public bool GetFlag(Byte flagPos) { return SacsHierarchyItem.GetFlag(Flags, flagPos); } /// Set flag value - position 1 - 16 - public void SetFlag (Byte flagPos, bool value) + public void SetFlag(Byte flagPos, bool value) { CheckChanged(GetFlag(flagPos), value); Flags = SacsHierarchyItem.SetFlag(Flags, flagPos, value); @@ -126,7 +126,7 @@ namespace Sarand.Net.Standard.Base.Bus //--------------------------------------------------------------- // Population. /// Copy common properties to this object. - protected void PopulateFrom (Data sourceData) + protected void PopulateFrom(Data sourceData) { Id = sourceData.Id; Notes = sourceData.Notes; @@ -136,7 +136,7 @@ namespace Sarand.Net.Standard.Base.Bus UpdateStamp = sourceData.UpdateStamp; } /// Copy comon properties to the target object. - internal void PopulateTo (Data targetData) + internal void PopulateTo(Data targetData) { targetData.PopulateFrom(this); } @@ -155,30 +155,30 @@ namespace Sarand.Net.Standard.Base.Bus } } /// Clear 'Changed' flag. - public void AcceptChanges () + public void AcceptChanges() { Changed = false; } //--------------------------------------------------------------- // Compare old and new property values and set 'Changed' if different. - protected void CheckChanged (SysId oldValue, SysId newValue) + protected void CheckChanged(SysId oldValue, SysId newValue) { if (Changed) return; // Compare by numeric value so that invalid values are equal. Changed = SysId.ToInt(oldValue) != SysId.ToInt(newValue); } - protected void CheckChanged (ItemId oldValue, ItemId newValue) + protected void CheckChanged(ItemId oldValue, ItemId newValue) { if (Changed) return; Changed = (oldValue.Type != newValue.Type) || (!oldValue.Id.Equals(newValue.Id)); } - protected void CheckChanged (String oldValue, String newValue) + protected void CheckChanged(String oldValue, String newValue) { if (Changed) return; Changed = !StringUtil.EmptyOnNull(oldValue).Equals(StringUtil.EmptyOnNull(newValue)); } - protected void CheckChanged (bool oldValue, bool newValue) + protected void CheckChanged(bool oldValue, bool newValue) { if (Changed) return; Changed = (oldValue != newValue); @@ -186,44 +186,45 @@ namespace Sarand.Net.Standard.Base.Bus protected void CheckChangedEnum(T oldValue, T newValue) where T : struct, IConvertible { if (!(oldValue is Enum) || !(newValue is Enum)) - throw new ArgumentException(GetType().Name+ ".CheckChangedEnum Parameters must be enumerated types. Type supplied: " + oldValue.GetType().Name + ", " + newValue.GetType().Name); + throw new ArgumentException(GetType().Name + ".CheckChangedEnum Parameters must be enumerated types. Type supplied: " + oldValue.GetType().Name + ", " + newValue.GetType().Name); if (Changed) return; Changed = ((int)(oldValue as IConvertible) != (int)(newValue as IConvertible)); } - protected void CheckChanged (long oldValue, long newValue) + protected void CheckChanged(long oldValue, long newValue) { if (Changed) return; Changed = (oldValue != newValue); } - protected void CheckChanged (double oldValue, double newValue) + protected void CheckChanged(double oldValue, double newValue) { if (Changed) return; Changed = (oldValue != newValue); } - protected void CheckChanged (decimal oldValue, decimal newValue) + protected void CheckChanged(decimal oldValue, decimal newValue) { if (Changed) return; Changed = (oldValue != newValue); } - protected void CheckChanged (DateTime oldValue, DateTime newValue) + protected void CheckChanged(DateTime oldValue, DateTime newValue) { if (Changed) return; Changed = !oldValue.Equals(newValue); } - protected void CheckChanged (List oldValues, List newValues) + protected void CheckChanged(IEnumerable oldValues, IEnumerable newValues) { if (Changed) return; Changed = !oldValues.ContentEquals(newValues); } - protected void CheckChanged (List oldValues, List newValues) + protected void CheckChanged(IEnumerable oldValues, IEnumerable newValues) { if (Changed) return; if (oldValues.Count() != newValues.Count()) Changed = true; else { - for (int idx = 0; idx < oldValues.Count(); idx++) + var combinedValues = oldValues.Zip(newValues, Tuple.Create); + foreach (var combinedValue in combinedValues) { - if (!oldValues[idx].Equals(newValues[idx])) + if (!combinedValue.Item1.Equals(combinedValue.Item2)) { Changed = true; return; @@ -231,7 +232,7 @@ namespace Sarand.Net.Standard.Base.Bus } } } - protected void CheckChanged (byte[] oldValue, byte[] newValue) + protected void CheckChanged(byte[] oldValue, byte[] newValue) { if (Changed) return; if ((oldValue == null) != (newValue != null)) Changed = true; @@ -271,17 +272,17 @@ namespace Sarand.Net.Standard.Base.Bus //------------------------------------------------------------------- // Construction. - protected SacsHierarchyItem () + protected SacsHierarchyItem() { } - protected SacsHierarchyItem (SysId id) + protected SacsHierarchyItem(SysId id) { data.Id = id; } //------------------------------------------------------------------- // Disposal. - protected override void Dispose (bool disposing) + protected override void Dispose(bool disposing) { if (disposing) { @@ -344,7 +345,7 @@ namespace Sarand.Net.Standard.Base.Bus protected set { data.Flags = value; } } /// Flags are positioned from 1, up to 16 allowed. - public static bool GetFlag (UInt16 flags, Byte flagPos) + public static bool GetFlag(UInt16 flags, Byte flagPos) { bool flag = false; if (flagPos > 0 && flagPos <= 16) @@ -352,12 +353,12 @@ namespace Sarand.Net.Standard.Base.Bus return flag; } /// Flags are positioned from 1, up to 16 allowed. - public bool GetFlag (Byte flagPos) + public bool GetFlag(Byte flagPos) { return GetFlag(data.Flags, flagPos); } /// Set flag value - position 1 - 16 - public static UInt16 SetFlag (UInt16 flags, Byte flagPos, bool value) + public static UInt16 SetFlag(UInt16 flags, Byte flagPos, bool value) { if (flagPos > 0 && flagPos <= 16) { @@ -370,7 +371,7 @@ namespace Sarand.Net.Standard.Base.Bus return flags; } /// Set flag value - position 1 - 16 - public void SetFlag (Byte flagPos, bool value) + public void SetFlag(Byte flagPos, bool value) { data.Flags = SetFlag(data.Flags, flagPos, value); } @@ -378,14 +379,14 @@ namespace Sarand.Net.Standard.Base.Bus //------------------------------------------------------------------- // Update stamps. public UpdateStamp CreateStamp { get { return data.CreateStamp; } } - public void SetCreateStamp (DateTime on, SysId by, String host) + public void SetCreateStamp(DateTime on, SysId by, String host) { CreateStamp.On = on; CreateStamp.By = by; CreateStamp.Host = host; } public UpdateStamp UpdateStamp { get { return data.UpdateStamp; } } - public void SetUpdateStamp (DateTime on, SysId by, String host) + public void SetUpdateStamp(DateTime on, SysId by, String host) { UpdateStamp.On = on; UpdateStamp.By = by; @@ -394,7 +395,7 @@ namespace Sarand.Net.Standard.Base.Bus //------------------------------------------------------------------- // Populate data item - only once on construction. - protected void SetData (Data data) + protected void SetData(Data data) { String fn = GetType().Name + ".SetData"; // Can only be replaced if currently internal class. @@ -422,14 +423,14 @@ namespace Sarand.Net.Standard.Base.Bus } } /// Clear the 'Changed' flag to indicate that no changes have been made. - public void AcceptChanges () + public void AcceptChanges() { Changed = false; } //------------------------------------------------------------------- // Format value for display. - public static String FormatForDisplay (String value, int maxLength = 0) + public static String FormatForDisplay(String value, int maxLength = 0) { if (StringUtil.IsEmpty(value)) return String.Empty; // Replace non-display characters. @@ -450,7 +451,7 @@ namespace Sarand.Net.Standard.Base.Bus public class Params { // Construction. - protected Params () + protected Params() { } /// Primary table alias to use if different from default. diff --git a/SacsStandardBase/Base/Core/DisposableCollection.cs b/SacsStandardBase/Base/Core/DisposableCollection.cs index 230f3de..80ed235 100644 --- a/SacsStandardBase/Base/Core/DisposableCollection.cs +++ b/SacsStandardBase/Base/Core/DisposableCollection.cs @@ -10,7 +10,7 @@ namespace Sarand.Net.Standard.Base.Core { //======================================================================= public sealed class DisposableCollection : Collection, IDisposable - where T : IDisposable + where T : class, IDisposable { //------------------------------------------------------------------- // Construction. @@ -47,10 +47,31 @@ namespace Sarand.Net.Standard.Base.Core /// public new void Add(T item) { - if (item != null) + if (item != null && !Contains(item)) base.Add(item); } + /// + /// Add list of items to the collection. + /// Null items are ignored. + /// Items that can't be cast to the required object type cause a debug break. + /// + public void AddRange(List items) where O : class, IDisposable + { + if (items != null && !items.IsEmpty()) + { + foreach (O item in items) + { + if (item == null) continue; + T obj = item as T; + if (obj != null) + Add(obj); + else if (SacsSystem.DebugMode) + Debugger.Break(); + } + } + } + //------------------------------------------------------------------- } //======================================================================= diff --git a/SacsStandardBase/Base/Core/SacsQueueDictionary.cs b/SacsStandardBase/Base/Core/SacsQueueDictionary.cs new file mode 100644 index 0000000..0d27ecd --- /dev/null +++ b/SacsStandardBase/Base/Core/SacsQueueDictionary.cs @@ -0,0 +1,115 @@ +using Sarand.Net.Standard.Base.App; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Sarand.Net.Standard.Base.Core +{ + //======================================================================= + /// + /// Dictionary with items queued as if in FIFO list. + /// + /// Type of key + /// Type of value + public class SacsQueueDictionary + { + //------------------------------------------------------------------- + // Data memners. + private readonly Queue queue = new Queue(); + private readonly Dictionary dictionary = new Dictionary(); + + //------------------------------------------------------------------- + // Properties. + public int Count { get { lock (dictionary) return queue.Count; } } + + //------------------------------------------------------------------- + /// + /// Is the KLey defined in the queue dictionary. + /// + /// + /// True if found, else false. + public bool HasValue(K key) + { + lock (dictionary) + { + return dictionary.ContainsKey(key); + } + } + + //------------------------------------------------------------------- + /// + /// Retrieve the value determined by the key. + /// + /// + /// Corresponding value if present, else default value. + public V GetValue(K key) + { + V value = default(V); + lock (dictionary) + { + dictionary.TryGetValue(key, out value); + } + return value; + } + + //------------------------------------------------------------------- + public bool SetEntry(K key, V value) + { + if (key == null || value == null) return false; + lock (dictionary) + { + if (dictionary.ContainsKey(key)) + { + // Existsing key. + // Replace value in dictionary. + dictionary[key] = value; + return true; + } + // New Key. + // Add to queue and set value in dictionary. + queue.Enqueue(key); + dictionary[key] = value; + return true; + } + if (SacsSystem.DebugMode) Validate(); + } + + //------------------------------------------------------------------- + /// + /// Remove the top n entries from the queue dictionary. + /// + /// + /// + public List> RemoveTopEntries(int maxEntries) + { + List> entries = new List>(); + lock (dictionary) + { + while (queue.Count > 0 && entries.Count < maxEntries) + { + K key = queue.Dequeue(); + V value = dictionary[key]; + entries.Add(new KeyValuePair(key, value)); + dictionary.Remove(key); + } + } + if (SacsSystem.DebugMode) Validate(); + return entries; + } + + //------------------------------------------------------------------- + // Internal utilities. + //------------------------------------------------------------------- + private void Validate() + { + lock (dictionary) + { + if (queue.Count != dictionary.Count) + throw new NotSupportedException("SacsQueueDictionary.Validate Inconsistent entry counts. Quete: " + queue.Count + ". Dictionary: " + dictionary.Count); + } + } + + //------------------------------------------------------------------- + } + //======================================================================= +} diff --git a/SacsStandardBase/Base/Dbas/OdbcUtil.cs b/SacsStandardBase/Base/Dbas/OdbcUtil.cs index ebcdb10..2987861 100644 --- a/SacsStandardBase/Base/Dbas/OdbcUtil.cs +++ b/SacsStandardBase/Base/Dbas/OdbcUtil.cs @@ -39,7 +39,7 @@ namespace Sarand.Net.Standard.Base.Dbas /// the name of an ODBC driver for Microsoft SQL Server, if one is present; null, otherwise. public static string GetOdbcSqlDriverName () { - List driverPrecedence = new List() { "SQL Server Native Client 14.0", "SQL Server Native Client 13.0", "SQL Server Native Client 12.0", "SQL Server Native Client 11.0", "SQL Server Native Client 10.0", "SQL Server Native Client 9.0", "SQL Server" }; + List driverPrecedence = new List() { "ODBC Driver 17 for SQL Server", "ODBC Driver 13 for SQL Server", "ODBC Driver 11 for SQL Server", "SQL Server Native Client 11.0", "SQL Server Native Client 10.0", "SQL Server Native Client 9.0", "SQL Server" }; string[] availableOdbcDrivers = GetOdbcDriverNames(); string driverName = null; if (availableOdbcDrivers != null) diff --git a/SacsStandardBase/Base/Helpers/SacsRandomHelper.cs b/SacsStandardBase/Base/Helpers/SacsRandomHelper.cs index c46966d..6b5bee7 100644 --- a/SacsStandardBase/Base/Helpers/SacsRandomHelper.cs +++ b/SacsStandardBase/Base/Helpers/SacsRandomHelper.cs @@ -1,4 +1,5 @@ -using System; +using Sarand.Net.Standard.Base.Utils; +using System; using System.Collections.Generic; using System.Security.Cryptography; using System.Text; @@ -49,6 +50,20 @@ namespace Sarand.Net.Standard.Base.Helpers //return Random.Next(fromInclusive, toExclusive); } + //------------------------------------------------------------------- + public static String getRandomLengthNumber(ushort maxLength=4) + { + String value = ""; + int len = GetInt32(1, maxLength + 1); + for (int i = 0; i < len; i++) + value += GetInt32(0,10); + if (StringUtil.IsEmpty(value)) + throw new NotSupportedException("getRandomLengthNumber Generated blank value"); + if (value.Length > maxLength) + throw new NotSupportedException("getRandomLengthNumber Generated excess length value"); + return value; + } + //------------------------------------------------------------------- } //======================================================================= diff --git a/SacsStandardBase/Base/Utils/DictionaryUtil.cs b/SacsStandardBase/Base/Utils/DictionaryUtil.cs index 0558605..5dffb73 100644 --- a/SacsStandardBase/Base/Utils/DictionaryUtil.cs +++ b/SacsStandardBase/Base/Utils/DictionaryUtil.cs @@ -1,5 +1,7 @@ using System; +using System.Collections; using System.Collections.Generic; +using System.Collections.Specialized; using System.Linq; namespace Sarand.Net.Standard.Base.Utils @@ -40,7 +42,7 @@ namespace Sarand.Net.Standard.Base.Utils // S t r i n g - I n t U t i l i t i e s //------------------------------------------------------------------- /// Increment the count against the specified key by the supplied value, creating the key's entry if needed. - public static void Increment (this IDictionary dictionary, String key, int increment = 1) + public static void Increment(this IDictionary dictionary, String key, int increment = 1) { if (!dictionary.ContainsKey(key)) dictionary[key] = increment; @@ -52,14 +54,14 @@ namespace Sarand.Net.Standard.Base.Utils // A d d T o L i s t V a l u e //------------------------------------------------------------------- /// Add key:object to dictionary where each value is a list of objects. - public static void Add (this Dictionary> dict, TKey key, TValue value) + public static void Add(this Dictionary> dict, TKey key, TValue value) { if (!dict.ContainsKey(key)) dict[key] = new List(); dict[key].Add(value); } /// Add key:objects to dictionary where each value is a list of objects. - public static void Add (this Dictionary> dict, TKey key, IEnumerable values) + public static void Add(this Dictionary> dict, TKey key, IEnumerable values) { if (!dict.ContainsKey(key)) dict[key] = new List(); @@ -70,11 +72,36 @@ namespace Sarand.Net.Standard.Base.Utils // A d d R a n g e //------------------------------------------------------------------- /// Add entries from another dictionary. - public static void AddRange (this Dictionary dict, Dictionary dictToAdd) + public static void AddRange(this Dictionary dict, Dictionary dictToAdd) { dictToAdd.ForEach(x => dict.Add(x.Key, x.Value)); } + //------------------------------------------------------------------- + // Orderd Dictionary + //------------------------------------------------------------------- + public static DictionaryEntry GetElementAt(this OrderedDictionary dictionary, int index) + { + return dictionary.Cast().ElementAt(index); + } + public static K GetKeyAt(this OrderedDictionary dictionary, int index) + { + return (K)dictionary.GetElementAt(index).Key; + } + public static V GetValue(this OrderedDictionary dictionary, K key) + { + if (dictionary == null || key == null) + return default(V); + try + { + return (V)dictionary.Cast().AsQueryable().Single(kvp => ((K)kvp.Key).Equals(key)).Value; + } + catch (Exception) + { + return default(V); + } + } + //------------------------------------------------------------------- } //======================================================================= diff --git a/SacsStandardBase/Base/Utils/ExceptionUtil.cs b/SacsStandardBase/Base/Utils/ExceptionUtil.cs index d50f872..2248291 100644 --- a/SacsStandardBase/Base/Utils/ExceptionUtil.cs +++ b/SacsStandardBase/Base/Utils/ExceptionUtil.cs @@ -12,7 +12,7 @@ namespace Sarand.Net.Standard.Base.Utils /// - \r\n replaced with \n /// - Duplicate lines removed. /// - public static String GetMessage (this Exception exc) + public static String GetMessage(this Exception exc) { List messageLines = new List(); foreach (String messageLine in (StringUtil.EmptyOnNull(exc?.Message) ?? "").Trim().ReplaceAll("\r\n", "\n").Split('\n')) @@ -29,7 +29,7 @@ namespace Sarand.Net.Standard.Base.Utils /// [ExceptionType]: [ExceptionMessage] /// followed by stack entries on separate lines. /// - public static String GetErrorStateMessage (this Exception exc, bool includeExceptionType = true) + public static String GetErrorStateMessage(this Exception exc, bool includeExceptionType = true) { return (includeExceptionType ? exc.GetType().Name + ": " : "") + GetMessage(exc); } @@ -40,14 +40,23 @@ namespace Sarand.Net.Standard.Base.Utils /// [ExceptionType]: [ExceptionMessage] /// followed by stack entries on separate lines. /// - public static String GetLogMessage (this Exception exc, int entries = 8, String stackEntryDelim = "\n\t") + public static String GetLogMessage(this Exception exc, int entries = 8, String stackEntryDelim = "\n\t") { - return exc.GetType().Name + ": " + GetMessage(exc) + exc.GetStackEntries(entries).Concat("", stackEntryDelim); + return exc.GetLogMessage("", entries, stackEntryDelim); + } + /// + /// Generate standard exception log message. + /// [ExceptionType] [message]: [ExceptionMessage] + /// followed by stack entries on separate lines. + /// + public static String GetLogMessage(this Exception exc, String message, int entries = 8, String stackEntryDelim = "\n\t") + { + return (exc.GetType().Name + " " + message + ": " + GetMessage(exc) + exc.GetStackEntries(entries).Concat("", stackEntryDelim)).TrimAll(); } //------------------------------------------------------------------- /// Retrieve stack entries, up to maximum number. - public static List GetStackEntries (this Exception exc, int entries = 0) + public static List GetStackEntries(this Exception exc, int entries = 0) { List stackEntries = new List(); stackEntries.AddRange(exc.StackTrace.Split(new String[] { "\r\n" }, (entries > 0 ? entries : 999), StringSplitOptions.None)); @@ -63,19 +72,19 @@ namespace Sarand.Net.Standard.Base.Utils // File handling exceptions. public class FileException : Exception { - public FileException (string message) : + public FileException(string message) : base(message) { } } public class ArchiveFileException : FileException { - public ArchiveFileException (string message) : + public ArchiveFileException(string message) : base(message) { } } public class FileExistsException : FileException { - public FileExistsException (string message) : + public FileExistsException(string message) : base(message) { } } diff --git a/SacsStandardBase/Base/Utils/StringListUtil.cs b/SacsStandardBase/Base/Utils/StringListUtil.cs index 917a307..fa57fa0 100644 --- a/SacsStandardBase/Base/Utils/StringListUtil.cs +++ b/SacsStandardBase/Base/Utils/StringListUtil.cs @@ -42,18 +42,18 @@ namespace Sarand.Net.Standard.Base.Utils // C o m p a r i s o n //------------------------------------------------------------------- /// Compare lists to verify that they contain the same value in the corresponding position. - public static bool ContentEquals (this List values, List target) + public static bool ContentEquals (this IEnumerable values, IEnumerable target) { - if (values.Count != target.Count) return false; + if (values.Count() != target.Count()) return false; var combinedValues = values.Zip(target, Tuple.Create); foreach (var combinedValue in combinedValues) if (!combinedValue.Item1.Equals(combinedValue.Item2)) return false; return true; } /// Compare lists to verify that they contain the same case-insensitive value in the corresponding position. - public static bool ContentEqualsCI (this List values, List target) + public static bool ContentEqualsCI (this IEnumerable values, IEnumerable target) { - if (values.Count != target.Count) return false; + if (values.Count() != target.Count()) return false; var combinedValues = values.Zip(target, Tuple.Create); foreach (var combinedValue in combinedValues) if (!combinedValue.Item1.EqualsCI(combinedValue.Item2)) return false; diff --git a/SacsStandardDbas/Dbas/Data/SacsDatabaseOdbc.cs b/SacsStandardDbas/Dbas/Data/SacsDatabaseOdbc.cs index 0f12e71..74475a1 100644 --- a/SacsStandardDbas/Dbas/Data/SacsDatabaseOdbc.cs +++ b/SacsStandardDbas/Dbas/Data/SacsDatabaseOdbc.cs @@ -22,14 +22,14 @@ namespace Sarand.Net.Standard.Dbas.Data // Data members. private String sqlConnectionString = ""; private readonly List tables = new List(); - public static readonly String DbCol_CreateOn = "CreateOn"; - public static readonly String DbCol_CreateBy = "CreateBy"; - public static readonly String DbCol_UpdateOn = "UpdateOn"; - public static readonly String DbCol_UpdateBy = "UpdateBy"; + public static readonly String DbCol_CreateOn = "CreateOn"; + public static readonly String DbCol_CreateBy = "CreateBy"; + public static readonly String DbCol_UpdateOn = "UpdateOn"; + public static readonly String DbCol_UpdateBy = "UpdateBy"; //------------------------------------------------------------------- // Construction. - public SacsDatabaseOdbc (DbmsType dbms, String databaseName, String connectionString) : base(dbms, databaseName, connectionString) + public SacsDatabaseOdbc(DbmsType dbms, String databaseName, String connectionString) : base(dbms, databaseName, connectionString) { if (dbms == DbmsType.MsSql) sqlConnectionString = connectionString; @@ -50,16 +50,16 @@ namespace Sarand.Net.Standard.Dbas.Data //------------------------------------------------------------------- // Connection. - public override void OnConnectionChanged () + public override void OnConnectionChanged() { } - public override DbConnection CreateConnection (bool forceOdbc = false) + public override DbConnection CreateConnection(bool forceOdbc = false) { if (!forceOdbc && DbmsType == DbmsType.MsSql && !StringUtil.IsEmpty(sqlConnectionString)) return new SqlConnection(sqlConnectionString); return new OdbcConnection(ConnectionString); } - public override DbDataAdapter CreateDataAdapter () + public override DbDataAdapter CreateDataAdapter() { return new OdbcDataAdapter(); } @@ -68,17 +68,17 @@ namespace Sarand.Net.Standard.Dbas.Data // I d e n t i t y G e n e r a t i o n //------------------------------------------------------------------- private DbDfnTable nextIdTableDfn = null; - public override SysId GetNextId (String objectName, DbUpdateInfo dbUpdateInfo, bool databaseTable = true, String idColumn = "Id") + public override SysId GetNextId(String objectName, DbUpdateInfo dbUpdateInfo, bool databaseTable = true, String idColumn = "Id") { 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+"'"; - bool hasCreateCols = (nextIdTableDfn.HasColumnByName (DbCol_CreateOn) && nextIdTableDfn.HasColumnByName (DbCol_CreateBy)); - bool hasUpdateCols = (nextIdTableDfn.HasColumnByName (DbCol_UpdateOn) && nextIdTableDfn.HasColumnByName (DbCol_UpdateBy)); + String filter = "(" + colObject + ")='" + objectName + "'"; + bool hasCreateCols = (nextIdTableDfn.HasColumnByName(DbCol_CreateOn) && nextIdTableDfn.HasColumnByName(DbCol_CreateBy)); + bool hasUpdateCols = (nextIdTableDfn.HasColumnByName(DbCol_UpdateOn) && nextIdTableDfn.HasColumnByName(DbCol_UpdateBy)); // Query the data. int nextIdValue = 1; @@ -87,7 +87,7 @@ namespace Sarand.Net.Standard.Dbas.Data qry.Columns.Add(colNextId, colAliasNextId); qry.Filters.Add(filter); //SaLogger.Debug(GetType().Name + ".GetNextId Query: " + qry.BuildQuery()); - DbResultSet_DataReader resultsSet = DbResultSet_DataReader.ExecuteQuery(this,qry.BuildQuery()); + DbResultSet_DataReader resultsSet = DbResultSet_DataReader.ExecuteQuery(this, qry.BuildQuery()); if (resultsSet != null && resultsSet.NextRecord()) { NamedValue.Map values = resultsSet.GetRecordValues(); @@ -132,7 +132,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(GetType().Name + ".GetNextId Insert query: " + insertQry); using (var dbConnection = CreateConnection()) using (var dbCommand = dbConnection.CreateCommand()) @@ -153,7 +153,7 @@ namespace Sarand.Net.Standard.Dbas.Data return Math.Max(0, (int)maxId.AsLong()) + 1; return 1; } - public override bool SetMinNextId (String objectName, SysId id, DbUpdateInfo dbUpdateInfo, bool databaseTable = true, String idColumn = "Id", bool force = false) + public override bool SetMinNextId(String objectName, SysId id, DbUpdateInfo dbUpdateInfo, bool databaseTable = true, String idColumn = "Id", bool force = false) { PopulateNextIdTableDfn(); @@ -161,7 +161,7 @@ namespace Sarand.Net.Standard.Dbas.Data //return true; } - private void PopulateNextIdTableDfn () + private void PopulateNextIdTableDfn() { if (nextIdTableDfn != null && nextIdTableDfn.Name.Equals(NextIdTable)) return; nextIdTableDfn = GetTableDfn(NextIdTable); @@ -171,7 +171,7 @@ namespace Sarand.Net.Standard.Dbas.Data // Q u e r y D a t a b a s e //------------------------------------------------------------------- // Query records. - public override IDbDataTable ExecuteQuery (String query) + public override IDbDataTable ExecuteQuery(String query) { String fn = GetType().Name + ".ExecuteQuery"; ClearErrorState(); @@ -198,7 +198,7 @@ namespace Sarand.Net.Standard.Dbas.Data } //------------------------------------------------------------------- /// Execute a non-query statement and return the row count. - public override int ExecuteNonQuery (string query) + public override int ExecuteNonQuery(string query) { String fn = GetType().Name + ".ExecuteNonQuery"; ClearErrorState(); @@ -223,7 +223,7 @@ namespace Sarand.Net.Standard.Dbas.Data } //------------------------------------------------------------------- /// Compile and execute an insert statement and return the row count. - public override int ExecuteInsert (String tableName, List columnNameValues) + public override int ExecuteInsert(String tableName, List columnNameValues) { String fn = GetType().Name + ".ExecuteInsert"; ClearErrorState(); @@ -252,7 +252,7 @@ namespace Sarand.Net.Standard.Dbas.Data } //------------------------------------------------------------------- /// Compile and execute an update statement and return the row count. - public override int ExecuteUpdate (String tableName, List columnNameValues, String filter) + public override int ExecuteUpdate(String tableName, List columnNameValues, String filter) { String fn = GetType().Name + ".ExecuteUpdate"; ClearErrorState(); @@ -282,7 +282,7 @@ namespace Sarand.Net.Standard.Dbas.Data } //------------------------------------------------------------------- /// Compile and execute a delete statement and return the row count. - public override int ExecuteDelete (String tableName, String filter) + public override int ExecuteDelete(String tableName, String filter) { String fn = GetType().Name + ".ExecuteDelete"; ClearErrorState(); @@ -311,13 +311,13 @@ namespace Sarand.Net.Standard.Dbas.Data //------------------------------------------------------------------- /// Retrieve specific row value. - public override DataValue GetRowValue (String tableName, String columnName, String filter) + public override DataValue GetRowValue(String tableName, String columnName, String filter) { ClearErrorState(); try { String colAlias = "DataValue"; - String query = "SELECT "+columnName+" '"+colAlias+"' FROM "+tableName+(!StringUtil.IsEmpty(filter)?" WHERE "+filter:""); + String query = "SELECT " + columnName + " '" + colAlias + "' FROM " + tableName + (!StringUtil.IsEmpty(filter) ? " WHERE " + filter : ""); using (DbResultSet dbResultSet = DbResultSet_DataReader.ExecuteQuery(this, query)) { if (dbResultSet.NextRecord()) @@ -336,7 +336,7 @@ namespace Sarand.Net.Standard.Dbas.Data //------------------------------------------------------------------- /// Get row count from Table applying optional filter. - public override long GetRowCount (String tableName, String filter) + public override long GetRowCount(String tableName, String filter) { ClearErrorState(); DataValue dataValue = GetRowValue(tableName, "Count(*)", filter); @@ -346,7 +346,7 @@ namespace Sarand.Net.Standard.Dbas.Data //------------------------------------------------------------------- /// Get calculated value from table - Sum, Min or Max. - public override DataValue GetRowValue (String tableName, String columnName, String filter, DbGetValueType getValueType) + public override DataValue GetRowValue(String tableName, String columnName, String filter, DbGetValueType getValueType) { ClearErrorState(); String fn = ""; @@ -364,143 +364,156 @@ 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 List GetTableNames (bool refresh = false) + public override List GetTableNames(bool refresh = false) { - // Only populate table names if not previously done. - if (tables.Count < 1 || refresh) + lock (tables) { - tables.Clear(); - using (DbConnection dbConnection = CreateConnection(true)) + // Only populate table names if not previously done. + if (tables.Count < 1 || refresh) { - dbConnection.Open(); - PopulateTableNames(dbConnection); - } - } - return tables.GetNames(); - } - public override List GetTableDfns (bool refresh = false) - { - if (refresh) ClearTableDfns(); - // Only populate table names and/or table schemas where not previously done. - if (tables.Count < 1 || tables.Exists(item => !item.HasColumns())) - { - // Use a single connection for table and schaema population. - using (DbConnection dbConnection = CreateConnection(true)) - { - dbConnection.Open(); - if (tables.Count < 1) - PopulateTableNames(dbConnection); - foreach (DbDfnTable table in tables.ToList()) + tables.Clear(); + using (DbConnection dbConnection = CreateConnection(true)) { - if (!table.HasColumns()) + dbConnection.Open(); + PopulateTableNames(dbConnection); + } + } + return tables.GetNames(); + } + } + public override List GetTableDfns(bool refresh = false) + { + lock (tables) + { + if (refresh) ClearTableDfns(); + // Only populate table names and/or table schemas where not previously done. + if (tables.Count < 1 || tables.Exists(item => !item.HasColumns())) + { + // Use a single connection for table and schaema population. + using (DbConnection dbConnection = CreateConnection(true)) + { + dbConnection.Open(); + if (tables.Count < 1) + PopulateTableNames(dbConnection); + foreach (DbDfnTable table in tables.ToList()) + { + if (!table.HasColumns()) + { + PopulateTableColumns(dbConnection, table); + PopulateTableIndices(dbConnection, table); + } + } + } + } + return tables.ToList(); + } + } + public void ClearTableDfns() + { + lock (tables) + tables.Clear(); + } + public override DbDfnTable GetTableDfn(String tableName, bool refresh = false) + { + lock (tables) + { + if (!tables.GetNames().Contains(tableName) || refresh) + { + // Remove current table definition. + tables.RemoveAll(item => item.Name.EqualsCI(tableName)); + } + // Only populate the specified table if required. + if (!tables.Exists(item => item.Name.EqualsCI(tableName) && item.Columns.Count > 0)) + { + using (DbConnection dbConnection = CreateConnection(true)) + { + dbConnection.Open(); + if (!tables.Exists(item => item.Name.EqualsCI(tableName))) + PopulateTableNames(dbConnection, tableName); + DbDfnTable table = tables.GetTableByName(tableName); + if (table != null && (!table.HasColumns() || refresh)) { PopulateTableColumns(dbConnection, table); PopulateTableIndices(dbConnection, table); } } } + return tables.GetTableByName(tableName); } - return tables.ToList(); - } - public void ClearTableDfns () - { - tables.Clear(); - } - public override DbDfnTable GetTableDfn (String tableName, bool refresh = false) - { - if (!tables.GetNames().Contains(tableName) || refresh) - { - // Remove current table definition. - tables.RemoveAll(item => item.Name.EqualsCI(tableName)); - } - // Only populate the specified table if required. - if (!tables.Exists(item => item.Name.EqualsCI(tableName) && item.Columns.Count > 0)) - { - using (DbConnection dbConnection = CreateConnection(true)) - { - dbConnection.Open(); - if (!tables.Exists(item => item.Name.EqualsCI(tableName))) - PopulateTableNames(dbConnection, tableName); - DbDfnTable table = tables.GetTableByName(tableName); - if (table != null && (!table.HasColumns() || refresh)) - { - PopulateTableColumns(dbConnection, table); - PopulateTableIndices(dbConnection, table); - } - } - } - return tables.GetTableByName(tableName); } //------------------------------------------------------------------- - private void PopulateTableNames (DbConnection dbConnection, String tableNameRestriction = null) + private void PopulateTableNames(DbConnection dbConnection, String tableNameRestriction = null) { - if (StringUtil.IsEmpty(tableNameRestriction) && tables.Count > 0) return; - if (!StringUtil.IsEmpty(tableNameRestriction) && tables.Exists(item => item.Name.Equals(tableNameRestriction))) return; - String fn = GetType().Name+".PopulateTableNames"; - if (SacsSystem.DebugMode) SaLogger.Debug(fn + (!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)) + lock (tables) { - //DataSet set = tableSchema.DataSet; - foreach (DataRow row in tableSchema.Rows) + if (StringUtil.IsEmpty(tableNameRestriction) && tables.Count > 0) return; + if (!StringUtil.IsEmpty(tableNameRestriction) && tables.Exists(item => item.Name.Equals(tableNameRestriction))) return; + String fn = GetType().Name + ".PopulateTableNames"; + if (SacsSystem.DebugMode) SaLogger.Debug(fn + (!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)) { - //----------------------------------------------------------- - // Columns are: Name Size Data Type Values - // 1. TABLE_CAT 255 12 VarChar - // 2. TABLE_SCHEM 128 12 VarChar - // 3. TABLE_NAME 128 12 VarChar - // 4. TABLE_TYPE 128 12 VarChar 'SYSTEM TABLE' 'TABLE' 'VIEW' - // 'GLOBAL TEMPORARY' 'LOCAL TEMPORARY' - // 'ALIAS' 'SYNONYM' - // 5. REMARKS 254 12 VarChar - // TABLE_CATALOG is the SQL alternative to TABLE_CAT - // TABLE_QUALIFIER is the ODBC 2.0 alternative to TABLE_CAT (ODBC 3.0). - // TABLE_SCHEMA is the SQL alternative to TABLE_SCHEM - // TABLE_OWNER is the ODBC 2.0 alternative to TABLE_SCHEM (ODBC 3.0). - // Variations: - // Sage Line 50: TABLE_QUALIFIER, TABLE_OWNER, TABLE_NAME, TABLE_TYPE, REMARKS. - // Sybase Advantage: QUALIFIERNAME, OWNERNAME, TABLENAME, TYPENAME, REMARKS - //----------------------------------------------------------- - String database = String.Empty, schema = String.Empty, tableName = String.Empty, type = String.Empty, remarks = String.Empty; - foreach (DataColumn column in tableSchema.Columns) - { - String colName = column.ColumnName; - String value = row[colName].ToString(); - 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")) - schema = value; - else if (colName.EqualsCI("TABLE_NAME") || colName.EqualsCI("TableName")) - tableName = value; - else if (colName.EqualsCI("TABLE_TYPE") || colName.EqualsCI("TypeName")) - type = value; - else if (colName.EqualsCI("REMARKS")) - remarks = value; - else - SaLogger.Warn(fn + " Unrecognised column name: '" + colName + "'"); - } - // TODO Why is Type sometimes "BASE TABLE"? - if (!StringUtil.IsEmpty(tableName) && (type.EqualsCI("Table") || type.EqualsCI("Base Table")) && (!schema.EqualsCI("sys") || !tableName.Left(9).EqualsCI("trace_xe_"))) + //DataSet set = tableSchema.DataSet; + foreach (DataRow row in tableSchema.Rows) { + //----------------------------------------------------------- + // Columns are: Name Size Data Type Values + // 1. TABLE_CAT 255 12 VarChar + // 2. TABLE_SCHEM 128 12 VarChar + // 3. TABLE_NAME 128 12 VarChar + // 4. TABLE_TYPE 128 12 VarChar 'SYSTEM TABLE' 'TABLE' 'VIEW' + // 'GLOBAL TEMPORARY' 'LOCAL TEMPORARY' + // 'ALIAS' 'SYNONYM' + // 5. REMARKS 254 12 VarChar + // TABLE_CATALOG is the SQL alternative to TABLE_CAT + // TABLE_QUALIFIER is the ODBC 2.0 alternative to TABLE_CAT (ODBC 3.0). + // TABLE_SCHEMA is the SQL alternative to TABLE_SCHEM + // TABLE_OWNER is the ODBC 2.0 alternative to TABLE_SCHEM (ODBC 3.0). + // Variations: + // Sage Line 50: TABLE_QUALIFIER, TABLE_OWNER, TABLE_NAME, TABLE_TYPE, REMARKS. + // Sybase Advantage: QUALIFIERNAME, OWNERNAME, TABLENAME, TYPENAME, REMARKS + //----------------------------------------------------------- + String database = String.Empty, schema = String.Empty, tableName = String.Empty, type = String.Empty, remarks = String.Empty; + foreach (DataColumn column in tableSchema.Columns) + { + String colName = column.ColumnName; + String value = row[colName].ToString(); + 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")) + schema = value; + else if (colName.EqualsCI("TABLE_NAME") || colName.EqualsCI("TableName")) + tableName = value; + else if (colName.EqualsCI("TABLE_TYPE") || colName.EqualsCI("TypeName")) + type = value; + else if (colName.EqualsCI("REMARKS")) + remarks = value; + else + SaLogger.Warn(fn + " Unrecognised column name: '" + colName + "'"); + } + // TODO Why is Type sometimes "BASE TABLE"? + if (!StringUtil.IsEmpty(tableName) && (type.EqualsCI("Table") || type.EqualsCI("Base Table")) && (!schema.EqualsCI("sys") || !tableName.Left(9).EqualsCI("trace_xe_"))) + { #if DEBUG - //SaLogger.Trace(fn+" Database="+database+", Schema="+schema+", Table="+tableName+", Type="+ type); + //SaLogger.Trace(fn+" Database="+database+", Schema="+schema+", Table="+tableName+", Type="+ type); #endif - tables.Add(new DbDfnTable(schema, tableName, remarks)); + tables.Add(new DbDfnTable(schema, tableName, remarks)); + } } } + List tablesUnsorted = tables.ToList(); + if (SacsSystem.DebugMode && tablesUnsorted.Exists(item => item == null)) + Debugger.Break(); + tables.Clear(); + tables.AddRange(tablesUnsorted.OrderBy(item => item.Name).ToList()); } - List tablesUnsorted = tables.ToList(); - if (SacsSystem.DebugMode && tablesUnsorted.Exists(item => item == null)) - Debugger.Break(); - tables.Clear(); - tables.AddRange(tablesUnsorted.OrderBy(item => item.Name).ToList()); } //------------------------------------------------------------------- - private void PopulateTableColumns (DbConnection dbConnection, DbDfnTable table) + private void PopulateTableColumns(DbConnection dbConnection, DbDfnTable table) { - String fn = GetType().Name+".PopulateTableColumns"; + String fn = GetType().Name + ".PopulateTableColumns"; if (SacsSystem.DebugMode) SaLogger.Debug(fn + " Table: " + table.Name); short columnPos = 0; String[] restrictions = new String[] { null, table.Schema, table.Name, null }; // database, owner, table name, column name @@ -703,9 +716,9 @@ namespace Sarand.Net.Standard.Dbas.Data } //------------------------------------------------------------------- - private void PopulateTableIndices (DbConnection dbConnection, DbDfnTable table) + private void PopulateTableIndices(DbConnection dbConnection, DbDfnTable table) { - String fn = GetType().Name+".PopulateTableIndices"; + String fn = GetType().Name + ".PopulateTableIndices"; String[] restrictions = new String[] { null, table.Schema, table.Name }; // database, owner, table name using (DataTable columnSchema = dbConnection.GetSchema(OdbcMetaDataCollectionNames.Indexes, restrictions)) {