From 96ace33dd0311df38ccde35fce5fe1a621af8e34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Granfeldt?= Date: Sat, 24 Sep 2022 08:58:58 +0200 Subject: [PATCH] Added better error handling for stored procedures. General logging formatting improvements. Merge pull request #21 --- .../Granfeldt.SQL.MA.UnitTests.cs | 229 ++++---- .../Properties/AssemblyInfo.cs | 1 - Granfeldt.SQL.MA/Configuration.cs | 372 ++++++------ Granfeldt.SQL.MA/MA/Sql.MA.Capabilities.cs | 42 +- Granfeldt.SQL.MA/MA/Sql.MA.Dispose.cs | 67 +-- Granfeldt.SQL.MA/MA/Sql.MA.Export.cs | 37 +- Granfeldt.SQL.MA/MA/Sql.MA.ExportDetached.cs | 384 ++++++------ Granfeldt.SQL.MA/MA/Sql.MA.Import.cs | 68 +-- Granfeldt.SQL.MA/MA/Sql.MA.ImportDetached.cs | 27 +- Granfeldt.SQL.MA/MA/Sql.MA.Main.cs | 84 +-- Granfeldt.SQL.MA/MA/Sql.MA.Parameters.cs | 7 +- Granfeldt.SQL.MA/Properties/AssemblyInfo.cs | 3 +- Granfeldt.SQL.MA/Schema.cs | 184 +++--- .../SqlMethods/SqlMethods.Connection.cs | 76 +-- .../SqlMethods/SqlMethods.Dispose.cs | 60 +- .../SqlMethods/SqlMethods.Export.cs | 555 +++++++++--------- .../SqlMethods/SqlMethods.Impersonation.cs | 20 +- .../SqlMethods/SqlMethods.Import.cs | 263 ++++----- .../SqlMethods/SqlMethods.Schema.cs | 100 ++-- .../SqlMethods/SqlMethods.StoredProcedures.cs | 164 +++--- Granfeldt.SQL.MA/Tracer.cs | 84 +-- 21 files changed, 1392 insertions(+), 1435 deletions(-) diff --git a/Granfeldt.SQL.MA.UnitTests/Granfeldt.SQL.MA.UnitTests.cs b/Granfeldt.SQL.MA.UnitTests/Granfeldt.SQL.MA.UnitTests.cs index 8fc92d3..eea37fd 100644 --- a/Granfeldt.SQL.MA.UnitTests/Granfeldt.SQL.MA.UnitTests.cs +++ b/Granfeldt.SQL.MA.UnitTests/Granfeldt.SQL.MA.UnitTests.cs @@ -1,122 +1,119 @@ -using System; +using Microsoft.MetadirectoryServices; using Microsoft.VisualStudio.TestTools.UnitTesting; -using Microsoft.MetadirectoryServices; -using System.Data; -using System.Data.SqlClient; namespace Granfeldt { - [TestClass] - public class SqlTests - { - SqlMethods methods = new SqlMethods(); - - [TestMethod] - public void GetObjectClasses() - { - methods.OpenConnection(); - foreach (string str in methods.GetObjectClasses()) - { - Tracer.TraceInformation("got-objectclass {0}", str); - } - methods.Dispose(); - } - - [TestMethod] - public void GetSingleValueColumns() - { - methods.OpenConnection(); - foreach (AttributeDefinition ad in methods.GetSchema(Configuration.TableNameSingle)) - { - } - methods.Dispose(); - } - - [TestMethod] - public void GetMultiValueColumns() - { - methods.OpenConnection(); - foreach (AttributeDefinition ad in methods.GetSchema(Configuration.TableNameMulti)) - { - } - methods.Dispose(); - } - - [TestMethod] - public void GetMASchema() - { - - using (SQLManagementAgent ma = new SQLManagementAgent()) - { - Configuration.Schema = ma.DefaultSchemaXml.XmlDeserializeFromString(); - Schema schema = ma.GetSchemaDetached(); - } - } - - [TestMethod] - public void GetFullImport() - { - using (SQLManagementAgent ma = new SQLManagementAgent()) - { - Configuration.Schema = ma.DefaultSchemaXml.XmlDeserializeFromString(); - Schema schema = ma.GetSchemaDetached(); - - ma.Schema = schema; - ma.ImportType = OperationType.Full; - - OpenImportConnectionRunStep dummyOpenImportRunStep = new OpenImportConnectionRunStep(); - - // fake runstep data - ma.ImportType = OperationType.Full; - ma.CustomData = ""; - ma.PageSize = 100; - - System.Collections.ObjectModel.KeyedCollection configParams = null; - ma.OpenImportConnectionDetached(configParams, schema, null); - - GetImportEntriesRunStep rs = new GetImportEntriesRunStep(); - - GetImportEntriesResults rest = new GetImportEntriesResults(); - rest.MoreToImport = true; - while (rest.MoreToImport) - { + [TestClass] + public class SqlTests + { + SqlMethods methods = new SqlMethods(); + + [TestMethod] + public void GetObjectClasses() + { + methods.OpenConnection(); + foreach (string str in methods.GetObjectClasses()) + { + Tracer.TraceInformation("got-objectclass {0}", str); + } + methods.Dispose(); + } + + [TestMethod] + public void GetSingleValueColumns() + { + methods.OpenConnection(); + foreach (AttributeDefinition ad in methods.GetSchema(Configuration.TableNameSingle)) + { + } + methods.Dispose(); + } + + [TestMethod] + public void GetMultiValueColumns() + { + methods.OpenConnection(); + foreach (AttributeDefinition ad in methods.GetSchema(Configuration.TableNameMulti)) + { + } + methods.Dispose(); + } + + [TestMethod] + public void GetMASchema() + { + + using (SQLManagementAgent ma = new SQLManagementAgent()) + { + Configuration.Schema = ma.DefaultSchemaXml.XmlDeserializeFromString(); + Schema schema = ma.GetSchemaDetached(); + } + } + + [TestMethod] + public void GetFullImport() + { + using (SQLManagementAgent ma = new SQLManagementAgent()) + { + Configuration.Schema = ma.DefaultSchemaXml.XmlDeserializeFromString(); + Schema schema = ma.GetSchemaDetached(); + + ma.Schema = schema; + ma.ImportType = OperationType.Full; + + OpenImportConnectionRunStep dummyOpenImportRunStep = new OpenImportConnectionRunStep(); + + // fake runstep data + ma.ImportType = OperationType.Full; + ma.CustomData = ""; + ma.PageSize = 100; + + System.Collections.ObjectModel.KeyedCollection configParams = null; + ma.OpenImportConnectionDetached(configParams, schema, null); + + GetImportEntriesRunStep rs = new GetImportEntriesRunStep(); + + GetImportEntriesResults rest = new GetImportEntriesResults(); + rest.MoreToImport = true; + while (rest.MoreToImport) + { rest = ma.GetImportEntriesDetached(rs); - } - - CloseImportConnectionRunStep dummyCloseImportRunStep = null; - ma.CloseImportConnectionDetached(dummyCloseImportRunStep); - } - } - [TestMethod] - public void GetDeltaImport() - { - using (SQLManagementAgent ma = new SQLManagementAgent()) - { - Configuration.Schema = ma.DefaultSchemaXml.XmlDeserializeFromString(); - Schema schema = ma.GetSchemaDetached(); - - // first get full data to get deltawatermark - ma.Schema = schema; - ma.ImportType = OperationType.Delta; - ma.CustomData = "140180"; - ma.PageSize = 1; - - System.Collections.ObjectModel.KeyedCollection configParams = null; - ma.OpenImportConnectionDetached(configParams, schema, null); - - GetImportEntriesRunStep rs = new GetImportEntriesRunStep(); - - GetImportEntriesResults rest = new GetImportEntriesResults(); - rest.MoreToImport = true; - while (rest.MoreToImport) - { - rest = ma.GetImportEntriesDetached(rs); - } - - CloseImportConnectionRunStep dummyCloseImportRunStep = null; - ma.CloseImportConnectionDetached(dummyCloseImportRunStep); - } - } - - } + } + + CloseImportConnectionRunStep dummyCloseImportRunStep = null; + ma.CloseImportConnectionDetached(dummyCloseImportRunStep); + } + } + [TestMethod] + public void GetDeltaImport() + { + using (SQLManagementAgent ma = new SQLManagementAgent()) + { + Configuration.Schema = ma.DefaultSchemaXml.XmlDeserializeFromString(); + Schema schema = ma.GetSchemaDetached(); + + // first get full data to get deltawatermark + ma.Schema = schema; + ma.ImportType = OperationType.Delta; + ma.CustomData = "140180"; + ma.PageSize = 1; + + System.Collections.ObjectModel.KeyedCollection configParams = null; + ma.OpenImportConnectionDetached(configParams, schema, null); + + GetImportEntriesRunStep rs = new GetImportEntriesRunStep(); + + GetImportEntriesResults rest = new GetImportEntriesResults(); + rest.MoreToImport = true; + while (rest.MoreToImport) + { + rest = ma.GetImportEntriesDetached(rs); + } + + CloseImportConnectionRunStep dummyCloseImportRunStep = null; + ma.CloseImportConnectionDetached(dummyCloseImportRunStep); + } + } + + } } diff --git a/Granfeldt.SQL.MA.UnitTests/Properties/AssemblyInfo.cs b/Granfeldt.SQL.MA.UnitTests/Properties/AssemblyInfo.cs index 40ad47c..ec5ed45 100644 --- a/Granfeldt.SQL.MA.UnitTests/Properties/AssemblyInfo.cs +++ b/Granfeldt.SQL.MA.UnitTests/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/Granfeldt.SQL.MA/Configuration.cs b/Granfeldt.SQL.MA/Configuration.cs index 876c199..876cdb3 100644 --- a/Granfeldt.SQL.MA/Configuration.cs +++ b/Granfeldt.SQL.MA/Configuration.cs @@ -5,196 +5,196 @@ namespace Granfeldt { - static class StringHandling - { - /// - /// Converts a SecureString to a normal string - /// - /// The encrypted string to be converted - /// - public static string ConvertToUnsecureString(this SecureString securePassword) - { - if (securePassword == null) - throw new ArgumentNullException("securePassword"); - - IntPtr unmanagedString = IntPtr.Zero; - try - { - unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(securePassword); - return Marshal.PtrToStringUni(unmanagedString); - } - finally - { - Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString); - } - } - } - - public enum ObjectClassType - { - Column, - Fixed - } - public enum DeltaColumnType - { - Rowversion, - DateTime - } - public static class Configuration - { - public static string ConnectionString = "data source=192.168.0.225;initial catalog=test;persist security info=true;user id={username};password={password};multipleactiveresultsets=true"; - public static string TypeOfAuthentication = Configuration.Parameters.AuthenticationTypeSQL; - public static string UserName = "sa"; - public static string Password = ""; - public static string Domain = ""; - - public static string TableNameSingle = "object"; - public static string TableNameMulti = "objectmv"; + static class StringHandling + { + /// + /// Converts a SecureString to a normal string + /// + /// The encrypted string to be converted + /// + public static string ConvertToUnsecureString(this SecureString securePassword) + { + if (securePassword == null) + throw new ArgumentNullException("securePassword"); + + IntPtr unmanagedString = IntPtr.Zero; + try + { + unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(securePassword); + return Marshal.PtrToStringUni(unmanagedString); + } + finally + { + Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString); + } + } + } + + public enum ObjectClassType + { + Column, + Fixed + } + public enum DeltaColumnType + { + Rowversion, + DateTime + } + public static class Configuration + { + public static string ConnectionString = "data source=192.168.0.225;initial catalog=test;persist security info=true;user id={username};password={password};multipleactiveresultsets=true"; + public static string TypeOfAuthentication = Configuration.Parameters.AuthenticationTypeSQL; + public static string UserName = "sa"; + public static string Password = ""; + public static string Domain = ""; + + public static string TableNameSingle = "object"; + public static string TableNameMulti = "objectmv"; public static string AnchorColumn = "_id"; - public static string ObjectClass = "_objectclass"; - public static string DeletedColumn = "_isdeleted"; + public static string ObjectClass = "_objectclass"; + public static string DeletedColumn = "_isdeleted"; public static string DeltaColumn = "_rowversion"; public static string DNColumn = "_id"; - public static string BackReferenceColumn = "_refid"; - - public static string ImportCommandBefore = ""; - public static string ImportCommandAfter = ""; - public static string ExportCommandBefore = ""; - public static string ExportCommandAfter = ""; - public static string ExportObjectCommandBefore = ""; - public static string ExportObjectCommandAfter = ""; + public static string BackReferenceColumn = "_refid"; + + public static string ImportCommandBefore = ""; + public static string ImportCommandAfter = ""; + public static string ExportCommandBefore = ""; + public static string ExportCommandAfter = ""; + public static string ExportObjectCommandBefore = ""; + public static string ExportObjectCommandAfter = ""; public static string DateFormat = "yyyy-MM-ddTHH:mm:ss.fff"; - public static string CommandTimeout = "30"; - - public static ObjectClassType ObjectClassType = ObjectClassType.Column; - public static DeltaColumnType DeltaColumnType = DeltaColumnType.Rowversion; - - public static SchemaConfiguration Schema = new SchemaConfiguration(); - - public static bool RunBeforeImport - { - get - { - return !string.IsNullOrEmpty(ImportCommandBefore); - } - } - public static bool RunAfterImport - { - get - { - return !string.IsNullOrEmpty(ImportCommandAfter); - } - } - public static bool RunBeforeExport - { - get - { - return !string.IsNullOrEmpty(ExportCommandBefore); - } - } - public static bool RunAfterExport - { - get - { - return !string.IsNullOrEmpty(ExportCommandAfter); - } - } - public static bool RunBeforeObjectExport - { - get - { - return !string.IsNullOrEmpty(ExportObjectCommandBefore); - } - } - public static bool RunAfterObjectExport - { - get - { - return !string.IsNullOrEmpty(ExportObjectCommandAfter); - } - } - - public static bool HasMultivalueTable - { - get - { - return !string.IsNullOrEmpty(TableNameMulti.Trim()); - } - } - public static bool HasDeletedColumn - { - get - { - return !string.IsNullOrEmpty(DeletedColumn.Trim()); - } - } - public static bool HasDeltaColumn - { - get - { - return !string.IsNullOrEmpty(DeltaColumn.Trim()); - } - } - - public static class Parameters - { - public const string ConnectionString = "Connection string"; - public const string TypeOfAuthentication = "Authentication Type"; - - public const string AuthenticationTypeSQL = "SQL"; - public const string AuthenticationTypeWindows = "Windows"; - - public const string Username = "Username"; - public const string Password = "Password"; - public const string Domain = "Domain"; - public const string SchemaConfiguration = "Schema Configuration"; - - public const string TableNameSingleValue = "Tablename"; - public const string TableNameMultiValue = "Tablename (multivalue)"; - - public const string ColumnAnchor = "Anchor column name"; - public const string ColumnDN = "DN column name"; - public const string ColumnIsDeleted = "IsDeleted column name"; - public const string ColumnMVAnchorReference = "Multivalue anchor reference column"; - - public const string TypeOfDelta = "Delta column type"; - public const string ColumnDelta = "Delta column name"; - - public const string TypeOfObjectClass = "Object class"; - public const string ColumnOrValueObjectClass = "Object class (name or column)"; - - public const string ImportCommandBefore = "Run before import"; - public const string ImportCommandAfter = "Run after import"; - public const string ExportCommandBefore = "Run before export"; - public const string ExportCommandAfter = "Run after export"; - public const string ExportObjectCommandBefore = "Run before export object"; - public const string ExportObjectCommandAfter = "Run after export object"; - //Define the Stored Procedure command timeout text - public const string CommandTimeout = "Stored Procedure timeout in seconds (min=30, max=99999, default=30)"; - - - public const string DateFormat = "Date format"; + public static string CommandTimeout = "30"; + + public static ObjectClassType ObjectClassType = ObjectClassType.Column; + public static DeltaColumnType DeltaColumnType = DeltaColumnType.Rowversion; + + public static SchemaConfiguration Schema = new SchemaConfiguration(); + + public static bool RunBeforeImport + { + get + { + return !string.IsNullOrEmpty(ImportCommandBefore); + } + } + public static bool RunAfterImport + { + get + { + return !string.IsNullOrEmpty(ImportCommandAfter); + } + } + public static bool RunBeforeExport + { + get + { + return !string.IsNullOrEmpty(ExportCommandBefore); + } + } + public static bool RunAfterExport + { + get + { + return !string.IsNullOrEmpty(ExportCommandAfter); + } + } + public static bool RunBeforeObjectExport + { + get + { + return !string.IsNullOrEmpty(ExportObjectCommandBefore); + } + } + public static bool RunAfterObjectExport + { + get + { + return !string.IsNullOrEmpty(ExportObjectCommandAfter); + } + } + + public static bool HasMultivalueTable + { + get + { + return !string.IsNullOrEmpty(TableNameMulti.Trim()); + } + } + public static bool HasDeletedColumn + { + get + { + return !string.IsNullOrEmpty(DeletedColumn.Trim()); + } + } + public static bool HasDeltaColumn + { + get + { + return !string.IsNullOrEmpty(DeltaColumn.Trim()); + } } - public static IEnumerable ReservedColumnNames - { - get - { - // we don't return DNColumnd, since we need that - yield return AnchorColumn; - if (ObjectClassType == ObjectClassType.Column) - { - yield return ObjectClass; - } - yield return DeletedColumn; - if (DeltaColumnType == DeltaColumnType.Rowversion) - { - yield return DeltaColumn; - } - yield return BackReferenceColumn; - yield return "export_password"; - } - } - - } + + public static class Parameters + { + public const string ConnectionString = "Connection string"; + public const string TypeOfAuthentication = "Authentication Type"; + + public const string AuthenticationTypeSQL = "SQL"; + public const string AuthenticationTypeWindows = "Windows"; + + public const string Username = "Username"; + public const string Password = "Password"; + public const string Domain = "Domain"; + public const string SchemaConfiguration = "Schema Configuration"; + + public const string TableNameSingleValue = "Tablename"; + public const string TableNameMultiValue = "Tablename (multivalue)"; + + public const string ColumnAnchor = "Anchor column name"; + public const string ColumnDN = "DN column name"; + public const string ColumnIsDeleted = "IsDeleted column name"; + public const string ColumnMVAnchorReference = "Multivalue anchor reference column"; + + public const string TypeOfDelta = "Delta column type"; + public const string ColumnDelta = "Delta column name"; + + public const string TypeOfObjectClass = "Object class"; + public const string ColumnOrValueObjectClass = "Object class (name or column)"; + + public const string ImportCommandBefore = "Run before import"; + public const string ImportCommandAfter = "Run after import"; + public const string ExportCommandBefore = "Run before export"; + public const string ExportCommandAfter = "Run after export"; + public const string ExportObjectCommandBefore = "Run before export object"; + public const string ExportObjectCommandAfter = "Run after export object"; + //Define the Stored Procedure command timeout text + public const string CommandTimeout = "Stored Procedure timeout in seconds (min=30, max=99999, default=30)"; + + + public const string DateFormat = "Date format"; + } + public static IEnumerable ReservedColumnNames + { + get + { + // we don't return DNColumnd, since we need that + yield return AnchorColumn; + if (ObjectClassType == ObjectClassType.Column) + { + yield return ObjectClass; + } + yield return DeletedColumn; + if (DeltaColumnType == DeltaColumnType.Rowversion) + { + yield return DeltaColumn; + } + yield return BackReferenceColumn; + yield return "export_password"; + } + } + + } } diff --git a/Granfeldt.SQL.MA/MA/Sql.MA.Capabilities.cs b/Granfeldt.SQL.MA/MA/Sql.MA.Capabilities.cs index 6e932c7..0a96976 100644 --- a/Granfeldt.SQL.MA/MA/Sql.MA.Capabilities.cs +++ b/Granfeldt.SQL.MA/MA/Sql.MA.Capabilities.cs @@ -4,27 +4,27 @@ namespace Granfeldt { public partial class SQLManagementAgent : IDisposable, IMAExtensible2GetCapabilities, IMAExtensible2GetSchema, IMAExtensible2GetParameters, IMAExtensible2CallImport, IMAExtensible2CallExport - { - MACapabilities IMAExtensible2GetCapabilities.Capabilities - { - get - { - Tracer.Enter(nameof(IMAExtensible2GetCapabilities.Capabilities)); - MACapabilities cap = new MACapabilities(); - cap.ExportPasswordInFirstPass = false; - cap.ConcurrentOperation = true; - cap.DeltaImport = true; - cap.DistinguishedNameStyle = MADistinguishedNameStyle.Generic; - cap.ExportType = MAExportType.AttributeUpdate; - cap.FullExport = true; - cap.ObjectConfirmation = MAObjectConfirmation.Normal; - cap.ObjectRename = false; - cap.NoReferenceValuesInFirstExport = false; - Tracer.Exit(nameof(IMAExtensible2GetCapabilities.Capabilities)); - return cap; - } - } + { + MACapabilities IMAExtensible2GetCapabilities.Capabilities + { + get + { + Tracer.Enter(nameof(IMAExtensible2GetCapabilities.Capabilities)); + MACapabilities cap = new MACapabilities(); + cap.ExportPasswordInFirstPass = false; + cap.ConcurrentOperation = true; + cap.DeltaImport = true; + cap.DistinguishedNameStyle = MADistinguishedNameStyle.Generic; + cap.ExportType = MAExportType.AttributeUpdate; + cap.FullExport = true; + cap.ObjectConfirmation = MAObjectConfirmation.Normal; + cap.ObjectRename = false; + cap.NoReferenceValuesInFirstExport = false; + Tracer.Exit(nameof(IMAExtensible2GetCapabilities.Capabilities)); + return cap; + } + } - } + } } diff --git a/Granfeldt.SQL.MA/MA/Sql.MA.Dispose.cs b/Granfeldt.SQL.MA/MA/Sql.MA.Dispose.cs index 63dc585..cc6f3a7 100644 --- a/Granfeldt.SQL.MA/MA/Sql.MA.Dispose.cs +++ b/Granfeldt.SQL.MA/MA/Sql.MA.Dispose.cs @@ -1,42 +1,37 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Microsoft.MetadirectoryServices; +using Microsoft.MetadirectoryServices; +using System; namespace Granfeldt { - public partial class SQLManagementAgent : IDisposable, IMAExtensible2GetCapabilities, IMAExtensible2GetSchema, IMAExtensible2GetParameters, IMAExtensible2CallImport, IMAExtensible2CallExport - { - private bool disposedValue = false; // To detect redundant calls - protected virtual void Dispose(bool disposing) - { - Tracer.Enter(nameof(Dispose)); - if (!disposedValue) - { - if (disposing) - { - Tracer.TraceInformation("disposing-managed-objects"); - } - disposedValue = true; - } - Tracer.Exit(nameof(Dispose)); - } - ~SQLManagementAgent() - { - // Do not change this code. Put cleanup code in Dispose(bool disposing) above. - Dispose(false); - } - // This code added to correctly implement the disposable pattern. - public void Dispose() - { - // Do not change this code. Put cleanup code in Dispose(bool disposing) above. - Dispose(true); - GC.SuppressFinalize(this); - } - } + public partial class SQLManagementAgent : IDisposable, IMAExtensible2GetCapabilities, IMAExtensible2GetSchema, IMAExtensible2GetParameters, IMAExtensible2CallImport, IMAExtensible2CallExport + { + private bool disposedValue = false; // To detect redundant calls + protected virtual void Dispose(bool disposing) + { + Tracer.Enter(nameof(Dispose)); + if (!disposedValue) + { + if (disposing) + { + Tracer.TraceInformation("disposing-managed-objects"); + } + disposedValue = true; + } + Tracer.Exit(nameof(Dispose)); + } + ~SQLManagementAgent() + { + // Do not change this code. Put cleanup code in Dispose(bool disposing) above. + Dispose(false); + } + // This code added to correctly implement the disposable pattern. + public void Dispose() + { + // Do not change this code. Put cleanup code in Dispose(bool disposing) above. + Dispose(true); + GC.SuppressFinalize(this); + } + } } diff --git a/Granfeldt.SQL.MA/MA/Sql.MA.Export.cs b/Granfeldt.SQL.MA/MA/Sql.MA.Export.cs index b0a252d..9108708 100644 --- a/Granfeldt.SQL.MA/MA/Sql.MA.Export.cs +++ b/Granfeldt.SQL.MA/MA/Sql.MA.Export.cs @@ -5,34 +5,13 @@ namespace Granfeldt { - public partial class SQLManagementAgent : IDisposable, IMAExtensible2GetCapabilities, IMAExtensible2GetSchema, IMAExtensible2GetParameters, IMAExtensible2CallImport, IMAExtensible2CallExport - { - int IMAExtensible2CallExport.ExportDefaultPageSize - { - get - { - return 100; - } - } - int IMAExtensible2CallExport.ExportMaxPageSize - { - get - { - return 500; - } - } - void IMAExtensible2CallExport.OpenExportConnection(KeyedCollection configParameters, Schema types, OpenExportConnectionRunStep exportRunStep) - { - OpenExportConnectionDetached(configParameters, types, exportRunStep); - } - PutExportEntriesResults IMAExtensible2CallExport.PutExportEntries(IList csentries) - { - return PutExportEntriesDetached(csentries); - } - void IMAExtensible2CallExport.CloseExportConnection(CloseExportConnectionRunStep exportRunStep) - { - CloseExportConnectionDetached(exportRunStep); - } - } + public partial class SQLManagementAgent : IDisposable, IMAExtensible2GetCapabilities, IMAExtensible2GetSchema, IMAExtensible2GetParameters, IMAExtensible2CallImport, IMAExtensible2CallExport + { + int IMAExtensible2CallExport.ExportDefaultPageSize => 100; + int IMAExtensible2CallExport.ExportMaxPageSize => 500; + void IMAExtensible2CallExport.OpenExportConnection(KeyedCollection configParameters, Schema types, OpenExportConnectionRunStep exportRunStep) => OpenExportConnectionDetached(configParameters, types, exportRunStep); + PutExportEntriesResults IMAExtensible2CallExport.PutExportEntries(IList csentries) => PutExportEntriesDetached(csentries); + void IMAExtensible2CallExport.CloseExportConnection(CloseExportConnectionRunStep exportRunStep) => CloseExportConnectionDetached(exportRunStep); + } } diff --git a/Granfeldt.SQL.MA/MA/Sql.MA.ExportDetached.cs b/Granfeldt.SQL.MA/MA/Sql.MA.ExportDetached.cs index 25f2481..03d4671 100644 --- a/Granfeldt.SQL.MA/MA/Sql.MA.ExportDetached.cs +++ b/Granfeldt.SQL.MA/MA/Sql.MA.ExportDetached.cs @@ -8,214 +8,212 @@ namespace Granfeldt { - public partial class SQLManagementAgent : IDisposable, IMAExtensible2GetCapabilities, IMAExtensible2GetSchema, IMAExtensible2GetParameters, IMAExtensible2CallImport, IMAExtensible2CallExport - { + public partial class SQLManagementAgent : IDisposable, IMAExtensible2GetCapabilities, IMAExtensible2GetSchema, IMAExtensible2GetParameters, IMAExtensible2CallImport, IMAExtensible2CallExport + { public int ExportBatchSize { get; set; } = 100; public OperationType ExportType { get; set; } string CSValueAsString(object Value, AttributeType DataType) - { - Tracer.TraceInformation("CSValueAsString {0}, {1}", Value == null ? "(null)" : Value.GetType().ToString(), DataType); - switch (DataType) - { - case AttributeType.Binary: - return new Guid((Byte[])Value).ToString(); - default: - return Value.ToString(); - } - } - public void OpenExportConnectionDetached(KeyedCollection configParameters, Schema types, OpenExportConnectionRunStep exportRunStep) - { - Tracer.Enter(nameof(OpenExportConnectionDetached)); - try - { - InitializeConfigParameters(configParameters); + { + Tracer.TraceInformation("CSValueAsString {0}, {1}", Value == null ? "(null)" : Value.GetType().ToString(), DataType); + switch (DataType) + { + case AttributeType.Binary: + return new Guid((Byte[])Value).ToString(); + default: + return Value.ToString(); + } + } + public void OpenExportConnectionDetached(KeyedCollection configParameters, Schema types, OpenExportConnectionRunStep exportRunStep) + { + Tracer.Enter(nameof(OpenExportConnectionDetached)); + try + { + InitializeConfigParameters(configParameters); - Schema = types; + Schema = types; - ExportType = exportRunStep.ExportType; - Tracer.TraceInformation("step-partition-id {0}", exportRunStep.StepPartition.Identifier); - Tracer.TraceInformation("step-partition-dn {0}", exportRunStep.StepPartition.DN); - Tracer.TraceInformation("step-partition-name {0}", exportRunStep.StepPartition.Name); - Tracer.TraceInformation("export-type {0}", ExportType); - ExportBatchSize = exportRunStep.BatchSize; - Tracer.TraceInformation("export-batch-size {0:n0}", ExportBatchSize); + ExportType = exportRunStep.ExportType; + Tracer.TraceInformation($"step-partition-id {exportRunStep.StepPartition.Identifier}"); + Tracer.TraceInformation($"step-partition-dn {exportRunStep.StepPartition.DN}"); + Tracer.TraceInformation($"step-partition-name {exportRunStep.StepPartition.Name}"); + Tracer.TraceInformation($"export-type {ExportType}"); + ExportBatchSize = exportRunStep.BatchSize; + Tracer.TraceInformation("export-batch-size {0:n0}", ExportBatchSize); - methods.OpenConnection(); + methods.OpenConnection(); - if (Configuration.RunBeforeExport) - { - List parameters = new List(); - parameters.Add(new SqlParameter("exporttype", ExportType.ToString())); - methods.RunStoredProcedure(Configuration.ExportCommandBefore, parameters, Convert.ToInt32(Configuration.CommandTimeout)); - } - } - catch (Exception ex) - { - Tracer.TraceError(nameof(OpenExportConnectionDetached), ex); - throw new TerminateRunException(ex.Message); - } - finally - { - Tracer.Exit(nameof(OpenExportConnectionDetached)); - } - } - //TODO: Remember to return identity from SQL if possible - public PutExportEntriesResults PutExportEntriesDetached(IList csentries) - { - Tracer.Enter(nameof(PutExportEntriesDetached)); - PutExportEntriesResults results = new PutExportEntriesResults(); - try - { - bool handleSoftDeletion = Configuration.HasDeletedColumn; - bool handleMultivalues = Configuration.HasMultivalueTable; + if (Configuration.RunBeforeExport) + { + List parameters = new List(); + parameters.Add(new SqlParameter("exporttype", ExportType.ToString())); + methods.RunStoredProcedure(Configuration.ExportCommandBefore, parameters, Convert.ToInt32(Configuration.CommandTimeout)); + } + } + catch (Exception ex) + { + Tracer.TraceError(nameof(OpenExportConnectionDetached), ex); + throw new TerminateRunException(ex.Message); + } + finally + { + Tracer.Exit(nameof(OpenExportConnectionDetached)); + } + } + public PutExportEntriesResults PutExportEntriesDetached(IList csentries) + { + Tracer.Enter(nameof(PutExportEntriesDetached)); + PutExportEntriesResults results = new PutExportEntriesResults(); + try + { + bool handleSoftDeletion = Configuration.HasDeletedColumn; + bool handleMultivalues = Configuration.HasMultivalueTable; - foreach (CSEntryChange exportChange in csentries) - { - List exportSqlCommands = new List(); - List attrchanges = new List(); + foreach (CSEntryChange exportChange in csentries) + { + List exportSqlCommands = new List(); + List attrchanges = new List(); - string anchor = null; - if (exportChange.AnchorAttributes.Count == 0) - { - Tracer.TraceInformation("no-anchor-present"); - } - else - { - anchor = CSValueAsString(exportChange.AnchorAttributes[0].Value, exportChange.AnchorAttributes[0].DataType); - } - string objectClass = exportChange.ObjectType; + string anchor = null; + if (exportChange.AnchorAttributes.Count == 0) + { + Tracer.TraceInformation("no-anchor-present"); + } + else + { + anchor = CSValueAsString(exportChange.AnchorAttributes[0].Value, exportChange.AnchorAttributes[0].DataType); + } + string objectClass = exportChange.ObjectType; - if (Configuration.RunBeforeObjectExport) - { - List parameters = new List(); - parameters.Add(new SqlParameter("anchor", anchor)); - parameters.Add(new SqlParameter("action", exportChange.ObjectModificationType.ToString())); - methods.RunStoredProcedure(Configuration.ExportObjectCommandBefore, parameters, Convert.ToInt32(Configuration.CommandTimeout)); - } + if (Configuration.RunBeforeObjectExport) + { + List parameters = new List(); + parameters.Add(new SqlParameter("anchor", anchor)); + parameters.Add(new SqlParameter("action", exportChange.ObjectModificationType.ToString())); + methods.RunStoredProcedure(Configuration.ExportObjectCommandBefore, parameters, Convert.ToInt32(Configuration.CommandTimeout)); + } - Tracer.TraceInformation("export-object {0}, cs-id: {1}, anchor: {2}, dn: {3} [{4}]", objectClass, exportChange.Identifier, anchor, exportChange.DN, exportChange.ObjectModificationType); - try - { - // first try to handle a delete - if (exportChange.ObjectModificationType == ObjectModificationType.Delete) - { - if (anchor == null) - { - throw new InvalidOperationException("cannot-delete-without-anchor"); - } + Tracer.TraceInformation("export-object {0}, cs-id: {1}, anchor: {2}, dn: {3} [{4}]", objectClass, exportChange.Identifier, anchor, exportChange.DN, exportChange.ObjectModificationType); + try + { + // first try to handle a delete + if (exportChange.ObjectModificationType == ObjectModificationType.Delete) + { + if (anchor == null) + { + throw new InvalidOperationException("cannot-delete-without-anchor"); + } - Tracer.TraceInformation("deleting-record type: {1}, anchor: {0}", objectClass, anchor); - methods.DeleteRecord(anchor, Configuration.HasMultivalueTable, handleSoftDeletion); - results.CSEntryChangeResults.Add(CSEntryChangeResult.Create(exportChange.Identifier, attrchanges, MAExportError.Success)); - continue; - } + Tracer.TraceInformation("deleting-record type: {1}, anchor: {0}", objectClass, anchor); + methods.DeleteRecord(anchor, Configuration.HasMultivalueTable, handleSoftDeletion); + results.CSEntryChangeResults.Add(CSEntryChangeResult.Create(exportChange.Identifier, attrchanges, MAExportError.Success)); + continue; + } - // if we get here its either an update or and add - if (exportChange.ObjectModificationType == ObjectModificationType.Add) - { - Tracer.TraceInformation("adding-record type: {1}, anchor: {0}", objectClass, anchor); - object newAnchor = anchor; // set it to incoming anchor - if (anchor != null && methods.ExistRecord(anchor)) - { - methods.Undelete(anchor); - } - else - { - methods.AddRecord(anchor, out newAnchor, objectClass); - } - attrchanges.Add(AttributeChange.CreateAttributeAdd(anchor, newAnchor)); - } + // if we get here its either an update or and add + if (exportChange.ObjectModificationType == ObjectModificationType.Add) + { + Tracer.TraceInformation("adding-record type: {1}, anchor: {0}", objectClass, anchor); + object newAnchor = anchor; // set it to incoming anchor + if (anchor != null && methods.ExistRecord(anchor)) + { + methods.Undelete(anchor); + } + else + { + methods.AddRecord(anchor, out newAnchor, objectClass); + } + attrchanges.Add(AttributeChange.CreateAttributeAdd(anchor, newAnchor)); + } - // updating attributes is common for add and update - foreach (string attributeChange in exportChange.ChangedAttributeNames) - { - AttributeChange ac = exportChange.AttributeChanges[attributeChange]; - Tracer.TraceInformation("attribute-change {0}, {1}", ac.Name, ac.ModificationType); - if (ac.IsMultiValued) - { - if (ac.ModificationType == AttributeModificationType.Delete) - { - methods.RemoveAllMultiValues(anchor, attributeChange, handleSoftDeletion); - continue; - } - foreach (ValueChange vc in ac.ValueChanges) - { - switch (vc.ModificationType) - { - case ValueModificationType.Add: - methods.AddMultiValue(anchor, attributeChange, vc.Value); - break; - case ValueModificationType.Delete: - methods.DeleteMultiValue(anchor, attributeChange, vc.Value, handleSoftDeletion); - break; - } - } - continue; - } - if (ac.ModificationType == AttributeModificationType.Delete) - { - methods.DeleteSingleValue(anchor, attributeChange); - continue; - } - foreach (ValueChange vc in ac.ValueChanges.Where(x => x.ModificationType == ValueModificationType.Add)) - { - Tracer.TraceInformation("singlevalue-change {0}, {1}", vc.ModificationType, vc.Value); - methods.AddSingleValue(anchor, attributeChange, vc.Value); - } - } - results.CSEntryChangeResults.Add(CSEntryChangeResult.Create(exportChange.Identifier, attrchanges, MAExportError.Success)); + // updating attributes is common for add and update + foreach (string attributeChange in exportChange.ChangedAttributeNames) + { + AttributeChange ac = exportChange.AttributeChanges[attributeChange]; + Tracer.TraceInformation("attribute-change {0}, {1}", ac.Name, ac.ModificationType); + if (ac.IsMultiValued) + { + if (ac.ModificationType == AttributeModificationType.Delete) + { + methods.RemoveAllMultiValues(anchor, attributeChange, handleSoftDeletion); + continue; + } + foreach (ValueChange vc in ac.ValueChanges) + { + switch (vc.ModificationType) + { + case ValueModificationType.Add: + methods.AddMultiValue(anchor, attributeChange, vc.Value); + break; + case ValueModificationType.Delete: + methods.DeleteMultiValue(anchor, attributeChange, vc.Value, handleSoftDeletion); + break; + } + } + continue; + } + if (ac.ModificationType == AttributeModificationType.Delete) + { + methods.DeleteSingleValue(anchor, attributeChange); + continue; + } + foreach (ValueChange vc in ac.ValueChanges.Where(x => x.ModificationType == ValueModificationType.Add)) + { + Tracer.TraceInformation("singlevalue-change {0}, {1}", vc.ModificationType, vc.Value); + methods.AddSingleValue(anchor, attributeChange, vc.Value); + } + } - if (Configuration.RunAfterObjectExport) - { - List parameters = new List(); - parameters.Add(new SqlParameter("anchor", anchor)); - parameters.Add(new SqlParameter("action", exportChange.ObjectModificationType.ToString())); - methods.RunStoredProcedure(Configuration.ExportObjectCommandAfter, parameters, Convert.ToInt32(Configuration.CommandTimeout)); - } - } - catch (Exception exportEx) - { - Tracer.TraceError(nameof(PutExportEntriesDetached), exportEx); - results.CSEntryChangeResults.Add(CSEntryChangeResult.Create(exportChange.Identifier, attrchanges, MAExportError.ExportErrorCustomContinueRun, "export-exception", exportEx.Message)); - throw; - } - } - } - catch (Exception ex) - { - Tracer.TraceError(nameof(PutExportEntriesDetached), ex); - throw; - } - finally - { - Tracer.Exit(nameof(PutExportEntriesDetached)); - } - return results; - } - public void CloseExportConnectionDetached(CloseExportConnectionRunStep exportRunStep) - { - Tracer.Enter(nameof(CloseExportConnectionDetached)); - try - { - if (Configuration.RunAfterExport) - { - List parameters = new List(); - parameters.Add(new SqlParameter("exporttype", ExportType.ToString())); - methods.RunStoredProcedure(Configuration.ExportCommandAfter, parameters, Convert.ToInt32(Configuration.CommandTimeout)); - } - methods.CloseConnection(); - } - catch (Exception ex) - { - Tracer.TraceError(nameof(CloseExportConnectionDetached), ex); - throw; - } - finally - { - Tracer.Exit(nameof(CloseExportConnectionDetached)); - } - } - } + if (Configuration.RunAfterObjectExport) + { + List parameters = new List(); + parameters.Add(new SqlParameter("anchor", anchor)); + parameters.Add(new SqlParameter("action", exportChange.ObjectModificationType.ToString())); + methods.RunStoredProcedure(Configuration.ExportObjectCommandAfter, parameters, Convert.ToInt32(Configuration.CommandTimeout)); + } + results.CSEntryChangeResults.Add(CSEntryChangeResult.Create(exportChange.Identifier, attrchanges, MAExportError.Success)); + } + catch (Exception exportEx) + { + Tracer.TraceError(nameof(PutExportEntriesDetached), exportEx); + results.CSEntryChangeResults.Add(CSEntryChangeResult.Create(exportChange.Identifier, attrchanges, MAExportError.ExportErrorCustomContinueRun, "export-exception", exportEx.Message)); + } + } + } + catch (Exception ex) + { + Tracer.TraceError(nameof(PutExportEntriesDetached), ex); + throw; + } + finally + { + Tracer.Exit(nameof(PutExportEntriesDetached)); + } + return results; + } + public void CloseExportConnectionDetached(CloseExportConnectionRunStep exportRunStep) + { + Tracer.Enter(nameof(CloseExportConnectionDetached)); + try + { + if (Configuration.RunAfterExport) + { + List parameters = new List(); + parameters.Add(new SqlParameter("exporttype", ExportType.ToString())); + methods.RunStoredProcedure(Configuration.ExportCommandAfter, parameters, Convert.ToInt32(Configuration.CommandTimeout)); + } + methods.CloseConnection(); + } + catch (Exception ex) + { + Tracer.TraceError(nameof(CloseExportConnectionDetached), ex); + throw; + } + finally + { + Tracer.Exit(nameof(CloseExportConnectionDetached)); + } + } + } } diff --git a/Granfeldt.SQL.MA/MA/Sql.MA.Import.cs b/Granfeldt.SQL.MA/MA/Sql.MA.Import.cs index 80cfdf9..892c99d 100644 --- a/Granfeldt.SQL.MA/MA/Sql.MA.Import.cs +++ b/Granfeldt.SQL.MA/MA/Sql.MA.Import.cs @@ -1,43 +1,37 @@ -using System; -using System.Collections.Generic; +using Microsoft.MetadirectoryServices; +using System; using System.Collections.ObjectModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Microsoft.MetadirectoryServices; -using System.Data; -using System.Globalization; namespace Granfeldt { - public partial class SQLManagementAgent : IDisposable, IMAExtensible2GetCapabilities, IMAExtensible2GetSchema, IMAExtensible2GetParameters, IMAExtensible2CallImport, IMAExtensible2CallExport - { - int IMAExtensible2CallImport.ImportDefaultPageSize - { - get - { - return 100; - } - } - int IMAExtensible2CallImport.ImportMaxPageSize - { - get - { - return 500; - } - } - OpenImportConnectionResults IMAExtensible2CallImport.OpenImportConnection(KeyedCollection configParameters, Schema types, OpenImportConnectionRunStep importRunStep) - { - return OpenImportConnectionDetached(configParameters, types, importRunStep); - } - GetImportEntriesResults IMAExtensible2CallImport.GetImportEntries(GetImportEntriesRunStep importRunStep) - { - return GetImportEntriesDetached(importRunStep); - } - CloseImportConnectionResults IMAExtensible2CallImport.CloseImportConnection(CloseImportConnectionRunStep importRunStep) - { - return CloseImportConnectionDetached(importRunStep); - } - } + public partial class SQLManagementAgent : IDisposable, IMAExtensible2GetCapabilities, IMAExtensible2GetSchema, IMAExtensible2GetParameters, IMAExtensible2CallImport, IMAExtensible2CallExport + { + int IMAExtensible2CallImport.ImportDefaultPageSize + { + get + { + return 100; + } + } + int IMAExtensible2CallImport.ImportMaxPageSize + { + get + { + return 500; + } + } + OpenImportConnectionResults IMAExtensible2CallImport.OpenImportConnection(KeyedCollection configParameters, Schema types, OpenImportConnectionRunStep importRunStep) + { + return OpenImportConnectionDetached(configParameters, types, importRunStep); + } + GetImportEntriesResults IMAExtensible2CallImport.GetImportEntries(GetImportEntriesRunStep importRunStep) + { + return GetImportEntriesDetached(importRunStep); + } + CloseImportConnectionResults IMAExtensible2CallImport.CloseImportConnection(CloseImportConnectionRunStep importRunStep) + { + return CloseImportConnectionDetached(importRunStep); + } + } } diff --git a/Granfeldt.SQL.MA/MA/Sql.MA.ImportDetached.cs b/Granfeldt.SQL.MA/MA/Sql.MA.ImportDetached.cs index 9a0c578..b391d0c 100644 --- a/Granfeldt.SQL.MA/MA/Sql.MA.ImportDetached.cs +++ b/Granfeldt.SQL.MA/MA/Sql.MA.ImportDetached.cs @@ -3,16 +3,13 @@ // november 13, 2019, soren granfeldt // - added handling of datetime types to use specific date format (same as FIM Service) to make sure local date formats are not used +using Microsoft.MetadirectoryServices; using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Microsoft.MetadirectoryServices; using System.Data; -using System.Globalization; using System.Data.SqlClient; +using System.Linq; namespace Granfeldt { @@ -58,10 +55,7 @@ public int PageSize } } - bool IsDateTimeType(Type type) - { - return typeof(DateTime) == type || typeof(DateTimeOffset) == type; - } + bool IsDateTimeType(Type type) => typeof(DateTime) == type || typeof(DateTimeOffset) == type; object GetSafeValue(DataRow dataRow, string attributeName, AttributeType attributeType, bool DeltaDate = false) { @@ -267,14 +261,14 @@ IEnumerable DataSetToCsEntryChanges(DataSet records) } catch (Exception iex) { - Tracer.TraceError("datasettocsentrychanges", iex); + Tracer.TraceError(nameof(DataSetToCsEntryChanges), iex); } yield return csentry; } } finally { - Tracer.Exit("datasettocsentrychanges"); + Tracer.Exit(nameof(DataSetToCsEntryChanges)); } } @@ -291,9 +285,9 @@ public OpenImportConnectionResults OpenImportConnectionDetached(KeyedCollection< CustomData = ImportType == OperationType.Delta ? importRunStep.CustomData : null; PageSize = importRunStep.PageSize; } - Tracer.TraceInformation("import-type {0}", ImportType); - Tracer.TraceInformation("customdata {0}", CustomData); - Tracer.TraceInformation("pagesize {0}", PageSize); + Tracer.TraceInformation($"import-type {ImportType}"); + Tracer.TraceInformation($"customdata {CustomData}"); + Tracer.TraceInformation($"pagesize {PageSize}"); Schema = types; @@ -384,13 +378,14 @@ public GetImportEntriesResults GetImportEntriesDetached(GetImportEntriesRunStep results.CustomData = CustomData == null ? "" : CustomData; results.CSEntries = batch; - Tracer.TraceInformation("more-to-import {0}", results.MoreToImport); - Tracer.TraceInformation("custom-data '{0}'", results.CustomData); + Tracer.TraceInformation($"more-to-import {results.MoreToImport}"); + Tracer.TraceInformation($"custom-data '{results.CustomData}'"); Tracer.TraceInformation("csobjects-returned {0:n0}", results.CSEntries.Count); } catch (Exception ex) { Tracer.TraceError(nameof(GetImportEntriesDetached), ex); + throw; } finally { diff --git a/Granfeldt.SQL.MA/MA/Sql.MA.Main.cs b/Granfeldt.SQL.MA/MA/Sql.MA.Main.cs index ea87c22..2967910 100644 --- a/Granfeldt.SQL.MA/MA/Sql.MA.Main.cs +++ b/Granfeldt.SQL.MA/MA/Sql.MA.Main.cs @@ -4,53 +4,53 @@ namespace Granfeldt { - public partial class SQLManagementAgent : IDisposable, IMAExtensible2GetCapabilities, IMAExtensible2GetSchema, IMAExtensible2GetParameters, IMAExtensible2CallImport, IMAExtensible2CallExport - { - // New-EventLog -Source "SQL Management Agent" -LogName Application - const string EventLogSource = "SQL Management Agent"; - const string EventLogName = "Application"; + public partial class SQLManagementAgent : IDisposable, IMAExtensible2GetCapabilities, IMAExtensible2GetSchema, IMAExtensible2GetParameters, IMAExtensible2CallImport, IMAExtensible2CallExport + { + // New-EventLog -Source "SQL Management Agent" -LogName Application + const string EventLogSource = "SQL Management Agent"; + const string EventLogName = "Application"; - SqlMethods methods = new SqlMethods(); + SqlMethods methods = new SqlMethods(); public Schema Schema { get; set; } = null; public SQLManagementAgent() - { - Tracer.Enter("initialize"); - try - { - System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly(); - FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(assembly.Location); - string version = fvi.FileVersion; - Tracer.TraceInformation("sqlma-version {0}", version); - Tracer.TraceInformation("reading-registry-settings"); + { + Tracer.Enter(nameof(SQLManagementAgent)); + try + { + System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly(); + FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(assembly.Location); + string version = fvi.FileVersion; + Tracer.TraceInformation($"sqlma-version {version}"); + Tracer.TraceInformation("reading-registry-settings"); - Tracer.TraceInformation("adding-eventlog-listener-for name: {0}, source: {1}", EventLogName, EventLogSource); - EventLog evl = new EventLog(EventLogName); - evl.Log = EventLogName; - evl.Source = EventLogSource; + Tracer.TraceInformation($"adding-eventlog-listener-for name: {EventLogName}, source: {EventLogSource}"); + EventLog evl = new EventLog(EventLogName); + evl.Log = EventLogName; + evl.Source = EventLogSource; - EventLogTraceListener eventLog = new EventLogTraceListener(EventLogSource); - eventLog.EventLog = evl; - EventTypeFilter filter = new EventTypeFilter(SourceLevels.Warning | SourceLevels.Error | SourceLevels.Critical); - eventLog.TraceOutputOptions = TraceOptions.Callstack; - eventLog.Filter = filter; - Tracer.Trace.Listeners.Add(eventLog); - if (!EventLog.SourceExists(EventLogSource)) - { - Tracer.TraceInformation("creating-eventlog-source '{0}'", EventLogSource); - EventLog.CreateEventSource(EventLogSource, EventLogName); - } - } - catch (Exception ex) - { - Tracer.TraceError("could-not-initialize", ex); - throw; - } - finally - { - Tracer.Exit("initialize"); - } - } - } + EventLogTraceListener eventLog = new EventLogTraceListener(EventLogSource); + eventLog.EventLog = evl; + EventTypeFilter filter = new EventTypeFilter(SourceLevels.Warning | SourceLevels.Error | SourceLevels.Critical); + eventLog.TraceOutputOptions = TraceOptions.Callstack; + eventLog.Filter = filter; + Tracer.Trace.Listeners.Add(eventLog); + if (!EventLog.SourceExists(EventLogSource)) + { + Tracer.TraceInformation($"creating-eventlog-source '{EventLogSource}'"); + EventLog.CreateEventSource(EventLogSource, EventLogName); + } + } + catch (Exception ex) + { + Tracer.TraceError("could-not-initialize", ex); + throw; + } + finally + { + Tracer.Exit(nameof(SQLManagementAgent)); + } + } + } } diff --git a/Granfeldt.SQL.MA/MA/Sql.MA.Parameters.cs b/Granfeldt.SQL.MA/MA/Sql.MA.Parameters.cs index 4e1b4b5..1891bc0 100644 --- a/Granfeldt.SQL.MA/MA/Sql.MA.Parameters.cs +++ b/Granfeldt.SQL.MA/MA/Sql.MA.Parameters.cs @@ -1,13 +1,10 @@ // december 3, 2017 :: søren granfeldt // - fixed issue with validation value in username parameter +using Microsoft.MetadirectoryServices; using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Microsoft.MetadirectoryServices; namespace Granfeldt { @@ -99,8 +96,6 @@ IList IMAExtensible2GetParameters.GetConfigParameters //Regex validating minimal 30 and max 99999 seconds: "^([3-9][0-9]|[0-9][0-9][0-9]|[0-9][0-9][0-9][0-9]|[0-9][0-9][0-9][0-9][0-9])$" configParametersDefinitions.Add(ConfigParameterDefinition.CreateStringParameter(Configuration.Parameters.CommandTimeout, "^([3-9][0-9]|[0-9][0-9][0-9]|[0-9][0-9][0-9][0-9]|[0-9][0-9][0-9][0-9][0-9])$", Configuration.CommandTimeout)); - - break; case ConfigParameterPage.Partition: break; diff --git a/Granfeldt.SQL.MA/Properties/AssemblyInfo.cs b/Granfeldt.SQL.MA/Properties/AssemblyInfo.cs index 1189581..e44bdca 100644 --- a/Granfeldt.SQL.MA/Properties/AssemblyInfo.cs +++ b/Granfeldt.SQL.MA/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following @@ -33,4 +32,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.2022.1053")] +[assembly: AssemblyFileVersion("1.0.2022.1054")] diff --git a/Granfeldt.SQL.MA/Schema.cs b/Granfeldt.SQL.MA/Schema.cs index bcba958..2256d6c 100644 --- a/Granfeldt.SQL.MA/Schema.cs +++ b/Granfeldt.SQL.MA/Schema.cs @@ -1,119 +1,117 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Text; -using System.Threading.Tasks; using System.Xml.Serialization; namespace Granfeldt { - public static class StringHelper - { - public static string XmlSerializeToString(this object objectInstance) - { - var serializer = new XmlSerializer(objectInstance.GetType()); - var sb = new StringBuilder(); + public static class StringHelper + { + public static string XmlSerializeToString(this object objectInstance) + { + var serializer = new XmlSerializer(objectInstance.GetType()); + var sb = new StringBuilder(); - using (TextWriter writer = new StringWriter(sb)) - { - serializer.Serialize(writer, objectInstance); - } + using (TextWriter writer = new StringWriter(sb)) + { + serializer.Serialize(writer, objectInstance); + } - return sb.ToString(); - } + return sb.ToString(); + } - public static T XmlDeserializeFromString(this string objectData) - { - return (T)XmlDeserializeFromString(objectData, typeof(T)); - } + public static T XmlDeserializeFromString(this string objectData) + { + return (T)XmlDeserializeFromString(objectData, typeof(T)); + } - public static object XmlDeserializeFromString(this string objectData, Type type) - { - var serializer = new XmlSerializer(type); - object result; + public static object XmlDeserializeFromString(this string objectData, Type type) + { + var serializer = new XmlSerializer(type); + object result; - using (TextReader reader = new StringReader(objectData)) - { - result = serializer.Deserialize(reader); - } + using (TextReader reader = new StringReader(objectData)) + { + result = serializer.Deserialize(reader); + } - return result; - } - } + return result; + } + } - [XmlTypeAttribute(AnonymousType = true)] - [XmlRootAttribute(ElementName = "configuration", Namespace = "", IsNullable = false)] - public partial class SchemaConfiguration - { - [XmlArray(ElementName = "objectclasses")] - [XmlArrayItemAttribute("objectclass", IsNullable = false)] - public List ObjectClasses = new List(); - } + [XmlTypeAttribute(AnonymousType = true)] + [XmlRootAttribute(ElementName = "configuration", Namespace = "", IsNullable = false)] + public partial class SchemaConfiguration + { + [XmlArray(ElementName = "objectclasses")] + [XmlArrayItemAttribute("objectclass", IsNullable = false)] + public List ObjectClasses = new List(); + } - [XmlTypeAttribute(AnonymousType = true)] - public partial class ObjectClass - { - [XmlArray("overrides")] - [XmlArrayItemAttribute("attribute", IsNullable = false)] - public List Overrides = new List(); + [XmlTypeAttribute(AnonymousType = true)] + public partial class ObjectClass + { + [XmlArray("overrides")] + [XmlArrayItemAttribute("attribute", IsNullable = false)] + public List Overrides = new List(); - [XmlArray("excludes")] - [XmlArrayItem("attribute", IsNullable = false)] - public List Excludes = new List(); + [XmlArray("excludes")] + [XmlArrayItem("attribute", IsNullable = false)] + public List Excludes = new List(); - [XmlAttribute(AttributeName = "name")] - public string Name; + [XmlAttribute(AttributeName = "name")] + public string Name; - public IEnumerable ExcludeList - { - get - { - foreach (DatabaseColumn dbc in Excludes) - yield return dbc.Name; - } - } - } + public IEnumerable ExcludeList + { + get + { + foreach (DatabaseColumn dbc in Excludes) + yield return dbc.Name; + } + } + } - public partial class DatabaseColumn - { - [XmlAttribute(AttributeName = "name")] - public string Name; - [XmlAttribute(AttributeName = "schematype")] - public OverrideType SchemaType; - [XmlAttribute(AttributeName = "type")] - public ReservedType Type; - } + public partial class DatabaseColumn + { + [XmlAttribute(AttributeName = "name")] + public string Name; + [XmlAttribute(AttributeName = "schematype")] + public OverrideType SchemaType; + [XmlAttribute(AttributeName = "type")] + public ReservedType Type; + } - public enum OverrideType - { - Unknown, - [XmlEnum(Name = "reference")] - Reference, - [XmlEnum(Name = "string")] - String, + public enum OverrideType + { + Unknown, + [XmlEnum(Name = "reference")] + Reference, + [XmlEnum(Name = "string")] + String, [XmlEnum(Name = "binary")] - Binary, + Binary, [XmlEnum(Name = "boolean")] - Boolean, + Boolean, [XmlEnum(Name = "integer")] - Integer - } + Integer + } - public enum ReservedType - { - Unknown, - [XmlEnum(Name = "anchor")] - Anchor, - [XmlEnum(Name = "objectclass")] - ObjectClass, - [XmlEnum(Name = "rowversion")] - RowVersion, - [XmlEnum(Name = "isdeleted")] - IsDeleted, - [XmlEnum(Name = "mvbackreference")] - MVBackReference, - [XmlEnum(Name = "dn")] - DN - } + public enum ReservedType + { + Unknown, + [XmlEnum(Name = "anchor")] + Anchor, + [XmlEnum(Name = "objectclass")] + ObjectClass, + [XmlEnum(Name = "rowversion")] + RowVersion, + [XmlEnum(Name = "isdeleted")] + IsDeleted, + [XmlEnum(Name = "mvbackreference")] + MVBackReference, + [XmlEnum(Name = "dn")] + DN + } } diff --git a/Granfeldt.SQL.MA/SqlMethods/SqlMethods.Connection.cs b/Granfeldt.SQL.MA/SqlMethods/SqlMethods.Connection.cs index 29b16f6..8b4a0d5 100644 --- a/Granfeldt.SQL.MA/SqlMethods/SqlMethods.Connection.cs +++ b/Granfeldt.SQL.MA/SqlMethods/SqlMethods.Connection.cs @@ -5,46 +5,46 @@ namespace Granfeldt { public partial class SqlMethods : IDisposable - { - SqlConnection con; + { + SqlConnection con; - public void OpenConnection() - { - Tracer.Enter(nameof(OpenConnection)); - - Configuration.ConnectionString = Configuration.ConnectionString.Replace("{username}", Configuration.UserName); - Configuration.ConnectionString = Configuration.ConnectionString.Replace("{domain}", Configuration.Domain); - string maskedConnectionString = Configuration.ConnectionString; - maskedConnectionString = Configuration.ConnectionString.Replace("{password}", "***"); - Configuration.ConnectionString = Configuration.ConnectionString.Replace("{password}", Configuration.Password); + public void OpenConnection() + { + Tracer.Enter(nameof(OpenConnection)); - Tracer.TraceInformation($"connection-string {maskedConnectionString}"); + Configuration.ConnectionString = Configuration.ConnectionString.Replace("{username}", Configuration.UserName); + Configuration.ConnectionString = Configuration.ConnectionString.Replace("{domain}", Configuration.Domain); + string maskedConnectionString = Configuration.ConnectionString; + maskedConnectionString = Configuration.ConnectionString.Replace("{password}", "***"); + Configuration.ConnectionString = Configuration.ConnectionString.Replace("{password}", Configuration.Password); - SetupImpersonationToken(); + Tracer.TraceInformation($"connection-string {maskedConnectionString}"); - con = new SqlConnection(Configuration.ConnectionString); - con.Open(); - if (con.State == System.Data.ConnectionState.Open) - { - Tracer.TraceInformation($"sql-server-version {con.ServerVersion}"); - } - Tracer.Exit(nameof(OpenConnection)); - } - public void CloseConnection() - { - Tracer.Enter(nameof(CloseConnection)); - Tracer.TraceInformation($"connection-state {con.State}"); - if (con.State != System.Data.ConnectionState.Closed) - { - con.Close(); - Tracer.TraceInformation("connection-closed"); - } - else - { - Tracer.TraceInformation("connection-already-closed"); - } - RevertImpersonation(); - Tracer.Exit(nameof(CloseConnection)); - } - } + SetupImpersonationToken(); + + con = new SqlConnection(Configuration.ConnectionString); + con.Open(); + if (con.State == System.Data.ConnectionState.Open) + { + Tracer.TraceInformation($"sql-server-version {con.ServerVersion}"); + } + Tracer.Exit(nameof(OpenConnection)); + } + public void CloseConnection() + { + Tracer.Enter(nameof(CloseConnection)); + Tracer.TraceInformation($"connection-state {con.State}"); + if (con.State != System.Data.ConnectionState.Closed) + { + con.Close(); + Tracer.TraceInformation("connection-closed"); + } + else + { + Tracer.TraceInformation("connection-already-closed"); + } + RevertImpersonation(); + Tracer.Exit(nameof(CloseConnection)); + } + } } \ No newline at end of file diff --git a/Granfeldt.SQL.MA/SqlMethods/SqlMethods.Dispose.cs b/Granfeldt.SQL.MA/SqlMethods/SqlMethods.Dispose.cs index 67ddf91..c27bd67 100644 --- a/Granfeldt.SQL.MA/SqlMethods/SqlMethods.Dispose.cs +++ b/Granfeldt.SQL.MA/SqlMethods/SqlMethods.Dispose.cs @@ -3,35 +3,35 @@ namespace Granfeldt { - public partial class SqlMethods : IDisposable - { + public partial class SqlMethods : IDisposable + { - // disposability - private bool disposedValue = false; // To detect redundant calls - protected virtual void Dispose(bool disposing) - { - Tracer.Enter("dispose-sql"); - if (!disposedValue) - { - if (disposing) - { - Tracer.TraceInformation("disposing-managed-objects"); - this.CloseConnection(); - } - disposedValue = true; - } - Tracer.Exit("dispose-sql"); - } - ~SqlMethods() - { - // Do not change this code. Put cleanup code in Dispose(bool disposing) above. - Dispose(false); - } - public void Dispose() - { - // Do not change this code. Put cleanup code in Dispose(bool disposing) above. - Dispose(true); - GC.SuppressFinalize(this); - } - } + // disposability + private bool disposedValue = false; // To detect redundant calls + protected virtual void Dispose(bool disposing) + { + Tracer.Enter(nameof(Dispose)); + if (!disposedValue) + { + if (disposing) + { + Tracer.TraceInformation("disposing-managed-objects"); + this.CloseConnection(); + } + disposedValue = true; + } + Tracer.Exit(nameof(Dispose)); + } + ~SqlMethods() + { + // Do not change this code. Put cleanup code in Dispose(bool disposing) above. + Dispose(false); + } + public void Dispose() + { + // Do not change this code. Put cleanup code in Dispose(bool disposing) above. + Dispose(true); + GC.SuppressFinalize(this); + } + } } \ No newline at end of file diff --git a/Granfeldt.SQL.MA/SqlMethods/SqlMethods.Export.cs b/Granfeldt.SQL.MA/SqlMethods/SqlMethods.Export.cs index d054e4f..b83e01a 100644 --- a/Granfeldt.SQL.MA/SqlMethods/SqlMethods.Export.cs +++ b/Granfeldt.SQL.MA/SqlMethods/SqlMethods.Export.cs @@ -1,285 +1,292 @@ using System; -using System.Collections.Generic; -using System.Data; using System.Data.SqlClient; -using System.Linq; -using System.Text; -// august 8, 2016 | soren granfeldt -// -changed string.Concat element order to fix buggy select scope_identity +// august 8, 2016 | soren granfeldt +// - changed string.Concat element order to fix buggy select scope_identity +// september 20, 2022 | soren granfeldt +// - add throw to try/catch to bubble any errors up namespace Granfeldt { - public partial class SqlMethods : IDisposable - { - public void AddRecord(object anchor, out object newId, string objectClass = null) - { - Tracer.Enter("addrecord"); - newId = anchor; - try - { - string query; - if (anchor == null) - { - query = string.Format("insert into {0} ([{1}]) values (@objectclass)", Configuration.TableNameSingle, Configuration.ObjectClass); - if (Configuration.ObjectClassType == ObjectClassType.Fixed) - { - query = string.Format("insert into {0} default values", Configuration.TableNameSingle); - } - } - else - { - query = string.Format("insert into {0} ([{1}], [{2}]) values (@anchor, @objectclass)", Configuration.TableNameSingle, Configuration.AnchorColumn, Configuration.ObjectClass); - if (Configuration.ObjectClassType == ObjectClassType.Fixed) - { - query = string.Format("insert into {0} ([{1}]) values (@anchor)", Configuration.TableNameSingle, Configuration.AnchorColumn); - } - } - query = string.Concat(query, "; select scope_identity();"); - using (SqlCommand cmd = new SqlCommand(query, con)) - { - cmd.Parameters.AddWithValue("@anchor", anchor); - cmd.Parameters.AddWithValue("@objectclass", objectClass); - Tracer.TraceInformation("run-query {0}", query); - newId = (object)cmd.ExecuteScalar(); - if (newId == null) - { - Tracer.TraceInformation("no-new-anchor-returned (scope_identity)"); - newId = anchor; - } - else - { - Tracer.TraceInformation("scope_identity-returned {0}", newId); - } - } - } - catch (Exception ex) - { - Tracer.TraceError("addrecord", ex); - } - finally - { - Tracer.Exit("addrecord"); - } - } - public bool ExistRecord(object anchor) - { - Tracer.Enter("existrecord"); - try - { - string query = string.Format("select [{0}] from {1} where [{0}] = @anchor;", Configuration.AnchorColumn, Configuration.TableNameSingle, Configuration.AnchorColumn); - using (SqlCommand cmd = new SqlCommand(query, con)) - { - cmd.Parameters.AddWithValue("@anchor", anchor); - Tracer.TraceInformation("run-query {0}", query); - object affectedRecords = (object)cmd.ExecuteScalar(); - Tracer.TraceInformation("exists {0}", affectedRecords != null); - return affectedRecords != null; - } - } - catch (Exception ex) - { - Tracer.TraceError("existrecord", ex); - } - finally - { - Tracer.Exit("existrecord"); - } - return false; - } - public void Undelete(object anchor) - { - Tracer.Enter("undelete"); - try - { - string query = string.Format("update {0} set [{1}] = 0 where [{2}] = @anchor", Configuration.TableNameSingle, Configuration.DeletedColumn, Configuration.AnchorColumn); - using (SqlCommand cmd = new SqlCommand(query, con)) - { - cmd.Parameters.AddWithValue("@anchor", anchor); - Tracer.TraceInformation("run-query {0}", query); - Tracer.TraceInformation("rows-affected {0:n0}", cmd.ExecuteNonQuery()); - } - } - catch (Exception ex) - { - Tracer.TraceError("undelete", ex); - } - finally - { - Tracer.Exit("undelete"); - } - } - public void DeleteRecord(object anchor, bool deleteMultiValues = false, bool softDelete = false) - { - Tracer.Enter("deleterecord"); - try - { - string query = null; + public partial class SqlMethods : IDisposable + { + public void AddRecord(object anchor, out object newId, string objectClass = null) + { + Tracer.Enter(nameof(AddRecord)); + newId = anchor; + try + { + string query; + if (anchor == null) + { + query = string.Format("insert into {0} ([{1}]) values (@objectclass)", Configuration.TableNameSingle, Configuration.ObjectClass); + if (Configuration.ObjectClassType == ObjectClassType.Fixed) + { + query = string.Format("insert into {0} default values", Configuration.TableNameSingle); + } + } + else + { + query = string.Format("insert into {0} ([{1}], [{2}]) values (@anchor, @objectclass)", Configuration.TableNameSingle, Configuration.AnchorColumn, Configuration.ObjectClass); + if (Configuration.ObjectClassType == ObjectClassType.Fixed) + { + query = string.Format("insert into {0} ([{1}]) values (@anchor)", Configuration.TableNameSingle, Configuration.AnchorColumn); + } + } + query = string.Concat(query, "; select scope_identity();"); + using (SqlCommand cmd = new SqlCommand(query, con)) + { + cmd.Parameters.AddWithValue("@anchor", anchor); + cmd.Parameters.AddWithValue("@objectclass", objectClass); + Tracer.TraceInformation("run-query {0}", query); + newId = (object)cmd.ExecuteScalar(); + if (newId == null) + { + Tracer.TraceInformation("no-new-anchor-returned (scope_identity)"); + newId = anchor; + } + else + { + Tracer.TraceInformation("scope_identity-returned {0}", newId); + } + } + } + catch (Exception ex) + { + Tracer.TraceError(nameof(AddRecord), ex); + throw; + } + finally + { + Tracer.Exit(nameof(AddRecord)); + } + } + public bool ExistRecord(object anchor) + { + Tracer.Enter(nameof(ExistRecord)); + try + { + string query = string.Format("select [{0}] from {1} where [{0}] = @anchor;", Configuration.AnchorColumn, Configuration.TableNameSingle, Configuration.AnchorColumn); + using (SqlCommand cmd = new SqlCommand(query, con)) + { + cmd.Parameters.AddWithValue("@anchor", anchor); + Tracer.TraceInformation("run-query {0}", query); + object affectedRecords = (object)cmd.ExecuteScalar(); + Tracer.TraceInformation("exists {0}", affectedRecords != null); + return affectedRecords != null; + } + } + catch (Exception ex) + { + Tracer.TraceError(nameof(ExistRecord), ex); + throw; + } + finally + { + Tracer.Exit(nameof(ExistRecord)); + } + return false; + } + public void Undelete(object anchor) + { + Tracer.Enter(nameof(Undelete)); + try + { + string query = string.Format("update {0} set [{1}] = 0 where [{2}] = @anchor", Configuration.TableNameSingle, Configuration.DeletedColumn, Configuration.AnchorColumn); + using (SqlCommand cmd = new SqlCommand(query, con)) + { + cmd.Parameters.AddWithValue("@anchor", anchor); + Tracer.TraceInformation("run-query {0}", query); + Tracer.TraceInformation("rows-affected {0:n0}", cmd.ExecuteNonQuery()); + } + } + catch (Exception ex) + { + Tracer.TraceError(nameof(Undelete), ex); + throw; + } + finally + { + Tracer.Exit(nameof(Undelete)); + } + } + public void DeleteRecord(object anchor, bool deleteMultiValues = false, bool softDelete = false) + { + Tracer.Enter(nameof(DeleteRecord)); + try + { + string query = null; - if (softDelete) - { - query = string.Format("update {0} set [{1}] = 1 where [{2}] = @anchor;", Configuration.TableNameSingle, Configuration.DeletedColumn, Configuration.AnchorColumn); - if (deleteMultiValues) - { - string.Concat(query, string.Format("update {0} set [{1}] = 1 where [{2}] = @anchor;", Configuration.TableNameMulti, Configuration.DeletedColumn, Configuration.BackReferenceColumn)); - } - } - else - { - query = string.Format("delete from {0} where [{1}] = @anchor;", Configuration.TableNameSingle, Configuration.AnchorColumn); - if (deleteMultiValues) - { - string.Concat(query, string.Format("delete from {0} where [{1}] = @anchor;", Configuration.TableNameMulti, Configuration.BackReferenceColumn)); - } - } - using (SqlCommand cmd = new SqlCommand(query, con)) - { - cmd.Parameters.AddWithValue("@anchor", anchor); - Tracer.TraceInformation("run-query {0}", query); - Tracer.TraceInformation("rows-affected {0:n0}", cmd.ExecuteNonQuery()); - } - } - catch (Exception ex) - { - Tracer.TraceError("addsinglevalue", ex); - } - finally - { - Tracer.Exit("addsinglevalue"); - } - } + if (softDelete) + { + query = string.Format("update {0} set [{1}] = 1 where [{2}] = @anchor;", Configuration.TableNameSingle, Configuration.DeletedColumn, Configuration.AnchorColumn); + if (deleteMultiValues) + { + string.Concat(query, string.Format("update {0} set [{1}] = 1 where [{2}] = @anchor;", Configuration.TableNameMulti, Configuration.DeletedColumn, Configuration.BackReferenceColumn)); + } + } + else + { + query = string.Format("delete from {0} where [{1}] = @anchor;", Configuration.TableNameSingle, Configuration.AnchorColumn); + if (deleteMultiValues) + { + string.Concat(query, string.Format("delete from {0} where [{1}] = @anchor;", Configuration.TableNameMulti, Configuration.BackReferenceColumn)); + } + } + using (SqlCommand cmd = new SqlCommand(query, con)) + { + cmd.Parameters.AddWithValue("@anchor", anchor); + Tracer.TraceInformation("run-query {0}", query); + Tracer.TraceInformation("rows-affected {0:n0}", cmd.ExecuteNonQuery()); + } + } + catch (Exception ex) + { + Tracer.TraceError(nameof(DeleteRecord), ex); + throw; + } + finally + { + Tracer.Exit(nameof(DeleteRecord)); + } + } - public void AddSingleValue(object anchor, string attributeName, object value) - { - Tracer.Enter("addsinglevalue"); - try - { - string query = string.Format("update {0} set [{1}] = @value where ([{2}] = @anchor)", Configuration.TableNameSingle, attributeName, Configuration.AnchorColumn); - using (SqlCommand cmd = new SqlCommand(query, con)) - { - cmd.Parameters.AddWithValue("@anchor", anchor); - cmd.Parameters.AddWithValue("@value", value); - Tracer.TraceInformation("run-query {0}", query); - Tracer.TraceInformation("rows-affected {0:n0}", cmd.ExecuteNonQuery()); - } - } - catch (Exception ex) - { - Tracer.TraceError("addsinglevalue", ex); - } - finally - { - Tracer.Exit("addsinglevalue"); - } - } - public void DeleteSingleValue(object anchor, string attributeName) - { - Tracer.Enter("deletesinglevalue"); - try - { - string query = null; - query = string.Format("update {0} set [{1}] = null where ([{2}] = @anchor)", Configuration.TableNameSingle, attributeName, Configuration.AnchorColumn); + public void AddSingleValue(object anchor, string attributeName, object value) + { + Tracer.Enter(nameof(AddSingleValue)); + try + { + string query = string.Format("update {0} set [{1}] = @value where ([{2}] = @anchor)", Configuration.TableNameSingle, attributeName, Configuration.AnchorColumn); + using (SqlCommand cmd = new SqlCommand(query, con)) + { + cmd.Parameters.AddWithValue("@anchor", anchor); + cmd.Parameters.AddWithValue("@value", value); + Tracer.TraceInformation("run-query {0}", query); + Tracer.TraceInformation("rows-affected {0:n0}", cmd.ExecuteNonQuery()); + } + } + catch (Exception ex) + { + Tracer.TraceError(nameof(AddSingleValue), ex); + throw; + } + finally + { + Tracer.Exit(nameof(AddSingleValue)); + } + } + public void DeleteSingleValue(object anchor, string attributeName) + { + Tracer.Enter(nameof(DeleteSingleValue)); + try + { + string query = null; + query = string.Format("update {0} set [{1}] = null where ([{2}] = @anchor)", Configuration.TableNameSingle, attributeName, Configuration.AnchorColumn); - using (SqlCommand cmd = new SqlCommand(query, con)) - { - cmd.Parameters.AddWithValue("@anchor", anchor); - Tracer.TraceInformation("run-query {0}", query); - Tracer.TraceInformation("rows-affected {0:n0}", cmd.ExecuteNonQuery()); - } - } - catch (Exception ex) - { - Tracer.TraceError("deletesinglevalue", ex); - } - finally - { - Tracer.Exit("deletesinglevalue"); - } - } + using (SqlCommand cmd = new SqlCommand(query, con)) + { + cmd.Parameters.AddWithValue("@anchor", anchor); + Tracer.TraceInformation("run-query {0}", query); + Tracer.TraceInformation("rows-affected {0:n0}", cmd.ExecuteNonQuery()); + } + } + catch (Exception ex) + { + Tracer.TraceError(nameof(DeleteSingleValue), ex); + throw; + } + finally + { + Tracer.Exit(nameof(DeleteSingleValue)); + } + } - public void AddMultiValue(object anchor, string attributeName, object value) - { - Tracer.Enter("addmultivalue"); - try - { - string query = string.Format("insert into {0} ([{1}], [{2}]) values (@anchor, @value)", Configuration.TableNameMulti, Configuration.BackReferenceColumn, attributeName); - using (SqlCommand cmd = new SqlCommand(query, con)) - { - cmd.Parameters.AddWithValue("@anchor", anchor); - cmd.Parameters.AddWithValue("@value", value); - Tracer.TraceInformation("run-query {0}", query); - Tracer.TraceInformation("rows-affected {0:n0}", cmd.ExecuteNonQuery()); - } - } - catch (Exception ex) - { - Tracer.TraceError("addmultivalue", ex); - } - finally - { - Tracer.Exit("addmultivalue"); - } - } - public void DeleteMultiValue(object anchor, string attributeName, object value, bool softDelete) - { - Tracer.Enter("deletemultivalue"); - try - { - string query = null; - if (softDelete) - { - query = string.Format("update {0} set [{1}] = 1 where ([{2}] = @anchor and [{3}] = @value)", Configuration.TableNameMulti, Configuration.DeletedColumn, Configuration.BackReferenceColumn, attributeName); - } - else - { - query = string.Format("delete from {0} where ([{1}] = @anchor and [{2}] = @value)", Configuration.TableNameMulti, Configuration.BackReferenceColumn, attributeName); - } - using (SqlCommand cmd = new SqlCommand(query, con)) - { - cmd.Parameters.AddWithValue("@anchor", anchor); - cmd.Parameters.AddWithValue("@value", value); - Tracer.TraceInformation("run-query {0}", query); - Tracer.TraceInformation("rows-affected {0:n0}", cmd.ExecuteNonQuery()); - } - } - catch (Exception ex) - { - Tracer.TraceError("deletemultivalue", ex); - } - finally - { - Tracer.Exit("deletemultivalue"); - } - } - public void RemoveAllMultiValues(object anchor, string attributeName, bool softDelete) - { - Tracer.Enter("removeallmultivalues"); - try - { - string query = null; - if (softDelete) - { - query = string.Format("update {0} set [{1}] = 1 where ([{2}] = @anchor and [{3}] is not null and [{1}] <> 1)", Configuration.TableNameMulti, Configuration.DeletedColumn, Configuration.BackReferenceColumn, attributeName); - } - else - { - query = string.Format("delete from {0} where ([{1}] = @anchor and [{2}] is not null)", Configuration.TableNameMulti, Configuration.BackReferenceColumn, attributeName); - } - using (SqlCommand cmd = new SqlCommand(query, con)) - { - cmd.Parameters.AddWithValue("@anchor", anchor); - Tracer.TraceInformation("run-query {0}", query); - Tracer.TraceInformation("rows-affected {0:n0}", cmd.ExecuteNonQuery()); - } - } - catch (Exception ex) - { - Tracer.TraceError("removeallmultivalues", ex); - } - finally - { - Tracer.Exit("removeallmultivalues"); - } - } - } + public void AddMultiValue(object anchor, string attributeName, object value) + { + Tracer.Enter(nameof(AddMultiValue)); + try + { + string query = string.Format("insert into {0} ([{1}], [{2}]) values (@anchor, @value)", Configuration.TableNameMulti, Configuration.BackReferenceColumn, attributeName); + using (SqlCommand cmd = new SqlCommand(query, con)) + { + cmd.Parameters.AddWithValue("@anchor", anchor); + cmd.Parameters.AddWithValue("@value", value); + Tracer.TraceInformation("run-query {0}", query); + Tracer.TraceInformation("rows-affected {0:n0}", cmd.ExecuteNonQuery()); + } + } + catch (Exception ex) + { + Tracer.TraceError(nameof(AddMultiValue), ex); + throw; + } + finally + { + Tracer.Exit(nameof(AddMultiValue)); + } + } + public void DeleteMultiValue(object anchor, string attributeName, object value, bool softDelete) + { + Tracer.Enter(nameof(DeleteMultiValue)); + try + { + string query = null; + if (softDelete) + { + query = string.Format("update {0} set [{1}] = 1 where ([{2}] = @anchor and [{3}] = @value)", Configuration.TableNameMulti, Configuration.DeletedColumn, Configuration.BackReferenceColumn, attributeName); + } + else + { + query = string.Format("delete from {0} where ([{1}] = @anchor and [{2}] = @value)", Configuration.TableNameMulti, Configuration.BackReferenceColumn, attributeName); + } + using (SqlCommand cmd = new SqlCommand(query, con)) + { + cmd.Parameters.AddWithValue("@anchor", anchor); + cmd.Parameters.AddWithValue("@value", value); + Tracer.TraceInformation("run-query {0}", query); + Tracer.TraceInformation("rows-affected {0:n0}", cmd.ExecuteNonQuery()); + } + } + catch (Exception ex) + { + Tracer.TraceError(nameof(DeleteMultiValue), ex); + throw; + } + finally + { + Tracer.Exit(nameof(DeleteMultiValue)); + } + } + public void RemoveAllMultiValues(object anchor, string attributeName, bool softDelete) + { + Tracer.Enter(nameof(RemoveAllMultiValues)); + try + { + string query = null; + if (softDelete) + { + query = string.Format("update {0} set [{1}] = 1 where ([{2}] = @anchor and [{3}] is not null and [{1}] <> 1)", Configuration.TableNameMulti, Configuration.DeletedColumn, Configuration.BackReferenceColumn, attributeName); + } + else + { + query = string.Format("delete from {0} where ([{1}] = @anchor and [{2}] is not null)", Configuration.TableNameMulti, Configuration.BackReferenceColumn, attributeName); + } + using (SqlCommand cmd = new SqlCommand(query, con)) + { + cmd.Parameters.AddWithValue("@anchor", anchor); + Tracer.TraceInformation("run-query {0}", query); + Tracer.TraceInformation("rows-affected {0:n0}", cmd.ExecuteNonQuery()); + } + } + catch (Exception ex) + { + Tracer.TraceError(nameof(RemoveAllMultiValues), ex); + throw; + } + finally + { + Tracer.Exit(nameof(RemoveAllMultiValues)); + } + } + } } diff --git a/Granfeldt.SQL.MA/SqlMethods/SqlMethods.Impersonation.cs b/Granfeldt.SQL.MA/SqlMethods/SqlMethods.Impersonation.cs index c900857..89d06d3 100644 --- a/Granfeldt.SQL.MA/SqlMethods/SqlMethods.Impersonation.cs +++ b/Granfeldt.SQL.MA/SqlMethods/SqlMethods.Impersonation.cs @@ -1,5 +1,4 @@ -using Microsoft.MetadirectoryServices; -using System; +using System; using System.Runtime.InteropServices; using System.Security; using System.Security.Principal; @@ -93,10 +92,7 @@ public enum LogonProvider IntPtr tokenDuplicate = IntPtr.Zero; WindowsImpersonationContext m_ImpersonationContext; - bool ShouldImpersonate() - { - return Configuration.TypeOfAuthentication == Configuration.Parameters.AuthenticationTypeWindows; - } + bool ShouldImpersonate() => Configuration.TypeOfAuthentication == Configuration.Parameters.AuthenticationTypeWindows; void SetupImpersonationToken() { @@ -190,13 +186,13 @@ void ShowIdentity() { using (WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent()) { - Tracer.TraceInformation("identity-name: {0}", currentIdentity.Name); - Tracer.TraceInformation("identity-token: {0}", currentIdentity.Token); - Tracer.TraceInformation("identity-user-value: {0}", currentIdentity.User.Value); + Tracer.TraceInformation($"identity-name: {currentIdentity.Name}"); + Tracer.TraceInformation($"identity-token: {currentIdentity.Token}"); + Tracer.TraceInformation($"identity-user-value: {currentIdentity.User.Value}"); if (currentIdentity.Actor != null) { - Tracer.TraceInformation("identity-actor: {0}", currentIdentity.Actor.Name); - Tracer.TraceInformation("identity-actor-auth-type: {0}", currentIdentity.Actor.AuthenticationType); + Tracer.TraceInformation($"identity-actor: {currentIdentity.Actor.Name}"); + Tracer.TraceInformation($"identity-actor-auth-type: {currentIdentity.Actor.AuthenticationType}"); } if (currentIdentity.Groups != null) { @@ -205,7 +201,7 @@ void ShowIdentity() try { NTAccount account = group.Translate(typeof(NTAccount)) as NTAccount; - Tracer.TraceInformation("group-membership {0}", account.Value); + Tracer.TraceInformation($"group-membership {account.Value}"); } catch (Exception ex) { diff --git a/Granfeldt.SQL.MA/SqlMethods/SqlMethods.Import.cs b/Granfeldt.SQL.MA/SqlMethods/SqlMethods.Import.cs index c64ae8e..d31f82e 100644 --- a/Granfeldt.SQL.MA/SqlMethods/SqlMethods.Import.cs +++ b/Granfeldt.SQL.MA/SqlMethods/SqlMethods.Import.cs @@ -7,140 +7,141 @@ namespace Granfeldt { - public partial class SqlMethods : IDisposable - { - public enum ImportType - { - Full, - Delta - } - - public DataSet ReadObjects(List anchors) - { - Tracer.Enter("readobjects"); - DataSet ds = new DataSet(); - try - { - string singleanchor = Configuration.AnchorColumn; - string multivalueanchorref = Configuration.BackReferenceColumn; - DataTable single = new DataTable(Configuration.TableNameSingle); - DataTable multi = Configuration.HasMultivalueTable ? new DataTable(Configuration.TableNameMulti) : null; - ds.Tables.Add(single); + public partial class SqlMethods : IDisposable + { + public enum ImportType + { + Full, + Delta + } - StringBuilder anchorList = new StringBuilder(); - for (int i = 0; i < anchors.Count; i++) - { - if (i > 0) anchorList.Append(","); - anchorList.AppendFormat("'{0}'", anchors[i]); - } + public DataSet ReadObjects(List anchors) + { + Tracer.Enter(nameof(ReadObjects)); + DataSet ds = new DataSet(); + try + { + string singleanchor = Configuration.AnchorColumn; + string multivalueanchorref = Configuration.BackReferenceColumn; + DataTable single = new DataTable(Configuration.TableNameSingle); + DataTable multi = Configuration.HasMultivalueTable ? new DataTable(Configuration.TableNameMulti) : null; + ds.Tables.Add(single); - StringBuilder query = new StringBuilder(); - query.AppendFormat("select * from {0} where [{1}] in ({2});", Configuration.TableNameSingle, singleanchor, anchorList); - if (Configuration.HasMultivalueTable) - { - query.AppendFormat("select * from {0} where [{1}] in ({2});", Configuration.TableNameMulti, multivalueanchorref, anchorList); - ds.Tables.Add(multi); - } - Tracer.TraceInformation("run-query '{0}'", query.ToString()); - using (SqlCommand cmd = new SqlCommand(query.ToString(), con)) - { - using (SqlDataReader dr = cmd.ExecuteReader()) - { - if (Configuration.HasMultivalueTable) - { - ds.Load(dr, LoadOption.OverwriteChanges, single, multi); - DataRelation relCustOrder = new DataRelation("mv", single.Columns[singleanchor], multi.Columns[multivalueanchorref]); - ds.Relations.Add(relCustOrder); - } - else - { - ds.Load(dr, LoadOption.OverwriteChanges, single); - } - } - } - } - catch (Exception ex) - { - Tracer.TraceError("readobjects {0}", ex.Message); - throw; - } - finally - { - Tracer.Exit("readobjects"); - } - return ds; - } - public IEnumerable GetAllAnchors(ImportType importType, string customData = null) - { - Tracer.Enter("getallanchors"); - List results = new List(); - try - { - List queries = new List(); + StringBuilder anchorList = new StringBuilder(); + for (int i = 0; i < anchors.Count; i++) + { + if (i > 0) anchorList.Append(","); + anchorList.AppendFormat("'{0}'", anchors[i]); + } - if (importType == ImportType.Full) - { - if (Configuration.HasDeletedColumn) - { - queries.Add(string.Format("select [{0}] from {1} where ([{2}] is null) or ([{2}] = 0)", Configuration.AnchorColumn, Configuration.TableNameSingle, Configuration.DeletedColumn)); - } - else - { - queries.Add(string.Format("select [{0}] from {1}", Configuration.AnchorColumn, Configuration.TableNameSingle)); - } - } - else - { - //TODO: should use SqlParameters to handle sql injections, but still fighting how to pass timestamps - string deltaWaterMark = null; - if (importType == ImportType.Delta) - { - if (Configuration.DeltaColumnType == DeltaColumnType.Rowversion) - { - customData = string.IsNullOrEmpty(customData) ? "00" : customData; - deltaWaterMark = string.Concat("0x", ulong.Parse(customData).ToString("X16")); - } - else - { - customData = string.IsNullOrEmpty(customData) ? DateTime.MinValue.ToString(Configuration.DateFormat) : customData; - deltaWaterMark = string.Concat("'", customData.TrimEnd('Z'), "'"); - } - } - queries.Add(string.Format("select [{0}] from {1} where ([{2}] > {3})", Configuration.AnchorColumn, Configuration.TableNameSingle, Configuration.DeltaColumn, deltaWaterMark)); - if (Configuration.HasMultivalueTable) - { - queries.Add(string.Format("select [{0}] from {1} where ([{2}] > {3})", Configuration.BackReferenceColumn, Configuration.TableNameMulti, Configuration.DeltaColumn, deltaWaterMark)); - } - } + StringBuilder query = new StringBuilder(); + query.AppendFormat("select * from {0} where [{1}] in ({2});", Configuration.TableNameSingle, singleanchor, anchorList); + if (Configuration.HasMultivalueTable) + { + query.AppendFormat("select * from {0} where [{1}] in ({2});", Configuration.TableNameMulti, multivalueanchorref, anchorList); + ds.Tables.Add(multi); + } + Tracer.TraceInformation($"run-query '{query.ToString()}'"); + using (SqlCommand cmd = new SqlCommand(query.ToString(), con)) + { + using (SqlDataReader dr = cmd.ExecuteReader()) + { + if (Configuration.HasMultivalueTable) + { + ds.Load(dr, LoadOption.OverwriteChanges, single, multi); + DataRelation relCustOrder = new DataRelation("mv", single.Columns[singleanchor], multi.Columns[multivalueanchorref]); + ds.Relations.Add(relCustOrder); + } + else + { + ds.Load(dr, LoadOption.OverwriteChanges, single); + } + } + } + } + catch (Exception ex) + { + Tracer.TraceError($"{nameof(ReadObjects)} {0}", ex.Message); + throw; + } + finally + { + Tracer.Exit(nameof(ReadObjects)); + } + return ds; + } + public IEnumerable GetAllAnchors(ImportType importType, string customData = null) + { + Tracer.Enter(nameof(GetAllAnchors)); + List results = new List(); + try + { + List queries = new List(); - foreach (string query in queries) - { - using (SqlCommand command = new SqlCommand(query, con)) - { - Tracer.TraceInformation("run-query '{0}'", query); - using (SqlDataReader reader = command.ExecuteReader()) - { - while (reader.Read()) - { - results.Add(reader.GetProviderSpecificValue(0)); - } - } - } - } - Tracer.TraceInformation("no-of-anchors {0:n0}", results.Count); - results = results.Distinct().ToList(); - Tracer.TraceInformation("no-of-distinct-anchors {0:n0}", results.Count); - } - catch (Exception ex) - { - Tracer.TraceError("getallanchors", ex); - } - finally - { - Tracer.Exit("getallanchors"); - } - return results; - } + if (importType == ImportType.Full) + { + if (Configuration.HasDeletedColumn) + { + queries.Add(string.Format("select [{0}] from {1} where ([{2}] is null) or ([{2}] = 0)", Configuration.AnchorColumn, Configuration.TableNameSingle, Configuration.DeletedColumn)); + } + else + { + queries.Add(string.Format("select [{0}] from {1}", Configuration.AnchorColumn, Configuration.TableNameSingle)); + } + } + else + { + //TODO: should use SqlParameters to handle sql injections, but still fighting how to pass timestamps + string deltaWaterMark = null; + if (importType == ImportType.Delta) + { + if (Configuration.DeltaColumnType == DeltaColumnType.Rowversion) + { + customData = string.IsNullOrEmpty(customData) ? "00" : customData; + deltaWaterMark = string.Concat("0x", ulong.Parse(customData).ToString("X16")); + } + else + { + customData = string.IsNullOrEmpty(customData) ? DateTime.MinValue.ToString(Configuration.DateFormat) : customData; + deltaWaterMark = string.Concat("'", customData.TrimEnd('Z'), "'"); + } + } + queries.Add(string.Format("select [{0}] from {1} where ([{2}] > {3})", Configuration.AnchorColumn, Configuration.TableNameSingle, Configuration.DeltaColumn, deltaWaterMark)); + if (Configuration.HasMultivalueTable) + { + queries.Add(string.Format("select [{0}] from {1} where ([{2}] > {3})", Configuration.BackReferenceColumn, Configuration.TableNameMulti, Configuration.DeltaColumn, deltaWaterMark)); + } + } - } + foreach (string query in queries) + { + using (SqlCommand command = new SqlCommand(query, con)) + { + Tracer.TraceInformation($"run-query '{query}'"); + using (SqlDataReader reader = command.ExecuteReader()) + { + while (reader.Read()) + { + results.Add(reader.GetProviderSpecificValue(0)); + } + } + } + } + Tracer.TraceInformation("no-of-anchors {0:n0}", results.Count); + results = results.Distinct().ToList(); + Tracer.TraceInformation("no-of-distinct-anchors {0:n0}", results.Count); + } + catch (Exception ex) + { + Tracer.TraceError(nameof(GetAllAnchors), ex); + throw; + } + finally + { + Tracer.Exit(nameof(GetAllAnchors)); + } + return results; + } + + } } diff --git a/Granfeldt.SQL.MA/SqlMethods/SqlMethods.Schema.cs b/Granfeldt.SQL.MA/SqlMethods/SqlMethods.Schema.cs index 65a0d82..f5d2cbf 100644 --- a/Granfeldt.SQL.MA/SqlMethods/SqlMethods.Schema.cs +++ b/Granfeldt.SQL.MA/SqlMethods/SqlMethods.Schema.cs @@ -9,55 +9,55 @@ namespace Granfeldt using System.Data.SqlClient; public partial class SqlMethods : IDisposable - { - // schema - public IEnumerable GetObjectClasses() - { - Tracer.Enter("getobjectclasses"); - try - { - string query = string.Format("select distinct {0} from {1}", Configuration.ObjectClass, Configuration.TableNameSingle); - Tracer.TraceInformation("run-query '{0}'", query); - SqlCommand command = new SqlCommand(query, con); - using (SqlDataReader reader = command.ExecuteReader()) - { - while (reader.Read()) - { - Tracer.TraceInformation("name: {0}, value: {1}", reader.GetName(0), reader[0]); - yield return reader[0] as string; - } - } - } - finally - { - Tracer.Exit("getobjectclasses"); - } - } - public IEnumerable GetSchema(string TableName) - { - Tracer.Enter("getschema"); - try - { - string query = string.Format("select top 1 * from {0}", TableName); - Tracer.TraceInformation("run-query '{0}'", query); - SqlCommand command = new SqlCommand(query, con); - using (SqlDataReader reader = command.ExecuteReader()) - { - while (reader.Read()) - { - for (int n = 0; n < reader.FieldCount; n++) - { - Tracer.TraceInformation("return-column: name: {0}, type: {1}", reader.GetName(n), reader.GetDataTypeName(n)); - yield return new AttributeDefinition(reader.GetName(n), reader.GetDataTypeName(n)); - } - } - } - } - finally - { - Tracer.Exit("getschema"); - } - } + { + // schema + public IEnumerable GetObjectClasses() + { + Tracer.Enter(nameof(GetObjectClasses)); + try + { + string query = string.Format("select distinct {0} from {1}", Configuration.ObjectClass, Configuration.TableNameSingle); + Tracer.TraceInformation("run-query '{0}'", query); + SqlCommand command = new SqlCommand(query, con); + using (SqlDataReader reader = command.ExecuteReader()) + { + while (reader.Read()) + { + Tracer.TraceInformation("name: {0}, value: {1}", reader.GetName(0), reader[0]); + yield return reader[0] as string; + } + } + } + finally + { + Tracer.Exit(nameof(GetObjectClasses)); + } + } + public IEnumerable GetSchema(string TableName) + { + Tracer.Enter(nameof(GetSchema)); + try + { + string query = $"select top 1 * from {TableName}"; + Tracer.TraceInformation($"run-query '{query}'"); + SqlCommand command = new SqlCommand(query, con); + using (SqlDataReader reader = command.ExecuteReader()) + { + while (reader.Read()) + { + for (int n = 0; n < reader.FieldCount; n++) + { + Tracer.TraceInformation($"return-column: name: {reader.GetName(n)}, type: {reader.GetDataTypeName(n)}"); + yield return new AttributeDefinition(reader.GetName(n), reader.GetDataTypeName(n)); + } + } + } + } + finally + { + Tracer.Exit(nameof(GetSchema)); + } + } - } + } } \ No newline at end of file diff --git a/Granfeldt.SQL.MA/SqlMethods/SqlMethods.StoredProcedures.cs b/Granfeldt.SQL.MA/SqlMethods/SqlMethods.StoredProcedures.cs index 3c6a445..ca370ee 100644 --- a/Granfeldt.SQL.MA/SqlMethods/SqlMethods.StoredProcedures.cs +++ b/Granfeldt.SQL.MA/SqlMethods/SqlMethods.StoredProcedures.cs @@ -1,91 +1,95 @@ -using System; +// september 20, 2022 | soren granfeldt +// - added throw statement for error in stored procedure execution + +using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; -using System.Linq; -using System.Text; namespace Granfeldt { - public partial class SqlMethods : IDisposable - { - public void RunStoredProcedure(string query) - { - Tracer.Enter("runstoredprocedure"); - try - { - using (SqlCommand cmd = new SqlCommand(query, con)) - { - cmd.CommandType = CommandType.StoredProcedure; - Tracer.TraceInformation("run-storedprocedure {0}", query); - Tracer.TraceInformation("rows-affected {0:n0}", cmd.ExecuteNonQuery()); - } - } - catch (Exception ex) - { - Tracer.TraceError("runstoredprocedure", ex); - } - finally - { - Tracer.Exit("runstoredprocedure"); - } - } - public void RunStoredProcedure(string query, IEnumerable parameters) - { - Tracer.Enter("runstoredprocedure"); - try - { - using (SqlCommand cmd = new SqlCommand(query, con)) - { - cmd.CommandType = CommandType.StoredProcedure; - foreach (SqlParameter param in parameters) - { - Tracer.TraceInformation("add-parameter name: {0}, value: '{1}'", param.ParameterName, param.SqlValue); - cmd.Parameters.Add(param); - } - Tracer.TraceInformation("run-storedprocedure {0}", query); - Tracer.TraceInformation("rows-affected {0:n0}", cmd.ExecuteNonQuery()); - } - } - catch (Exception ex) - { - Tracer.TraceError("runstoredprocedure", ex); - } - finally - { - Tracer.Exit("runstoredprocedure"); - } - } + public partial class SqlMethods : IDisposable + { + public void RunStoredProcedure(string query) + { + Tracer.Enter(nameof(RunStoredProcedure)); + try + { + using (SqlCommand cmd = new SqlCommand(query, con)) + { + cmd.CommandType = CommandType.StoredProcedure; + Tracer.TraceInformation("run-storedprocedure {0}", query); + Tracer.TraceInformation("rows-affected {0:n0}", cmd.ExecuteNonQuery()); + } + } + catch (Exception ex) + { + Tracer.TraceError(nameof(RunStoredProcedure), ex); + throw; + } + finally + { + Tracer.Exit(nameof(RunStoredProcedure)); + } + } + public void RunStoredProcedure(string query, IEnumerable parameters) + { + Tracer.Enter(nameof(RunStoredProcedure)); + try + { + using (SqlCommand cmd = new SqlCommand(query, con)) + { + cmd.CommandType = CommandType.StoredProcedure; + foreach (SqlParameter param in parameters) + { + Tracer.TraceInformation("add-parameter name: {0}, value: '{1}'", param.ParameterName, param.SqlValue); + cmd.Parameters.Add(param); + } + Tracer.TraceInformation("run-storedprocedure {0}", query); + Tracer.TraceInformation("rows-affected {0:n0}", cmd.ExecuteNonQuery()); + } + } + catch (Exception ex) + { + Tracer.TraceError(nameof(RunStoredProcedure), ex); + throw; + } + finally + { + Tracer.Exit(nameof(RunStoredProcedure)); + } + } - public void RunStoredProcedure(string query, IEnumerable parameters, int CommandTimeout) - { - Tracer.Enter("runstoredprocedure"); - try - { - using (SqlCommand cmd = new SqlCommand(query, con)) - { - cmd.CommandType = CommandType.StoredProcedure; + public void RunStoredProcedure(string query, IEnumerable parameters, int CommandTimeout) + { + Tracer.Enter(nameof(RunStoredProcedure)); + try + { + using (SqlCommand cmd = new SqlCommand(query, con)) + { + cmd.CommandType = CommandType.StoredProcedure; //Set the command timeout in seconds (Source: https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.commandtimeout?view=netframework-4.5.2 - cmd.CommandTimeout = CommandTimeout; + cmd.CommandTimeout = CommandTimeout; - foreach (SqlParameter param in parameters) - { - Tracer.TraceInformation("add-parameter name: {0}, value: '{1}'", param.ParameterName, param.SqlValue); - cmd.Parameters.Add(param); - } - Tracer.TraceInformation("run-storedprocedure {0} with command timeout: {1}", query, CommandTimeout); - Tracer.TraceInformation("rows-affected {0:n0}", cmd.ExecuteNonQuery()); - } - } - catch (Exception ex) - { - Tracer.TraceError("runstoredprocedure", ex); - } - finally - { - Tracer.Exit("runstoredprocedure"); - } - } - } + foreach (SqlParameter param in parameters) + { + Tracer.TraceInformation($"add-parameter name: {param.ParameterName}, value: '{param.SqlValue}'"); + cmd.Parameters.Add(param); + } + Tracer.TraceInformation($"run-storedprocedure {query} with command timeout: {CommandTimeout}"); + Tracer.TraceInformation("rows-affected {0:n0}", cmd.ExecuteNonQuery()); + } + } + catch (Exception ex) + { + Tracer.TraceError(nameof(RunStoredProcedure), ex); + throw; + } + finally + { + Tracer.Exit(nameof(RunStoredProcedure)); + } + } + } } diff --git a/Granfeldt.SQL.MA/Tracer.cs b/Granfeldt.SQL.MA/Tracer.cs index a0d0474..d3c8574 100644 --- a/Granfeldt.SQL.MA/Tracer.cs +++ b/Granfeldt.SQL.MA/Tracer.cs @@ -3,47 +3,47 @@ namespace Granfeldt { - public static class Tracer - { - //TODO: convert ident to stringbuilder - const string SwitchName = "SQLMA"; - const string SourceName = "SQL.MA"; - public static TraceSource Trace = new TraceSource(SourceName, SourceLevels.All); - static string IndentText = ""; + public static class Tracer + { + //TODO: convert ident to stringbuilder + const string SwitchName = "SQLMA"; + const string SourceName = "SQL.MA"; + public static TraceSource Trace = new TraceSource(SourceName, SourceLevels.All); + static string IndentText = ""; - public static void Enter(string entryPoint) - { - TraceInformation("enter {0}", entryPoint); - } - public static void Exit(string entryPoint) - { - TraceInformation("exit {0}", entryPoint); - } - public static void TraceInformation(string message, params object[] param) - { - Trace.TraceInformation(IndentText + message, param); - } - public static void TraceWarning(string message, params object[] param) - { - Trace.TraceEvent(TraceEventType.Warning, -1, IndentText + message, param); - } - public static void TraceError(string message, int id, params object[] param) - { - Trace.TraceEvent(TraceEventType.Error, id, IndentText + message, param); - } - public static void TraceError(string message, Exception ex) - { - Trace.TraceEvent(TraceEventType.Error, ex.HResult, IndentText + "{0}, {1}", message, ex.Message); - } - public static void TraceError(string message, params object[] param) - { - TraceError(message, -2, param); - } - static Tracer() - { - SourceSwitch sw = new SourceSwitch(SwitchName, SwitchName); - sw.Level = SourceLevels.All; - Trace.Switch = sw; - } - } + public static void Enter(string entryPoint) + { + TraceInformation("enter {0}", entryPoint); + } + public static void Exit(string entryPoint) + { + TraceInformation("exit {0}", entryPoint); + } + public static void TraceInformation(string message, params object[] param) + { + Trace.TraceInformation(IndentText + message, param); + } + public static void TraceWarning(string message, params object[] param) + { + Trace.TraceEvent(TraceEventType.Warning, -1, IndentText + message, param); + } + public static void TraceError(string message, int id, params object[] param) + { + Trace.TraceEvent(TraceEventType.Error, id, IndentText + message, param); + } + public static void TraceError(string message, Exception ex) + { + Trace.TraceEvent(TraceEventType.Error, ex.HResult, IndentText + "{0}, {1}", message, ex.Message); + } + public static void TraceError(string message, params object[] param) + { + TraceError(message, -2, param); + } + static Tracer() + { + SourceSwitch sw = new SourceSwitch(SwitchName, SwitchName); + sw.Level = SourceLevels.All; + Trace.Switch = sw; + } + } }