diff --git a/PesterTests/mysql.tests.ps1 b/PesterTests/mysql.tests.ps1 index b6caf1f..9ec4c70 100644 --- a/PesterTests/mysql.tests.ps1 +++ b/PesterTests/mysql.tests.ps1 @@ -98,7 +98,7 @@ InModuleScope SimplySql { Invoke-SqlBulkCopy -DestinationConnectionName bcp -SourceQuery $query -DestinationTable "mysql.tmpTable2" -Notify | Should -Be 65536 - + Close-SqlConnection -ConnectionName bcp } diff --git a/README.md b/README.md index b7b2ca8..147cf9b 100644 --- a/README.md +++ b/README.md @@ -31,11 +31,10 @@ It has been released to PowerShellGallery. Installation is as simple as This module requires PowerShell Version 5.0 or greater ## Latest Version - +### 1.9.0 +* Updated classes to use `::new()` constructor. thanks @joalcorn +* Updated MySql provider to use new library (8.0.28). thanks @twerthi ### 1.8.0 * Minor Update, enhancing progress notifications for Invoke-SqlBulkCopy, you can now specify -NotifyAction and pass in a scriptblock -### 1.7.0 - -* Minor update to expose the transaction object to the user via the new `Get-SqlTransaction` cmdlet. [View Version History](VersionHistory.md) \ No newline at end of file diff --git a/SimplySql/Classes.ps1 b/SimplySql/Classes.ps1 index 4fdd1ae..1ace371 100644 --- a/SimplySql/Classes.ps1 +++ b/SimplySql/Classes.ps1 @@ -5,7 +5,7 @@ Class ProviderBase { [int]$CommandTimeout = 30 [System.Data.IDbConnection]$Connection [System.Data.IDbTransaction]$Transaction - [System.Collections.Generic.Queue[SqlMessage]]$Messages = (New-Object 'System.Collections.Generic.Queue[SqlMessage]') + [System.Collections.Generic.Queue[SqlMessage]]$Messages = ([System.Collections.Generic.Queue[SqlMessage]]::new()) ProviderBase() { If($this.GetType().Name -eq "ProviderBase") { Throw [System.InvalidOperationException]::new("ProviderBase must be inherited!") } } @@ -154,4 +154,4 @@ Class ProviderBase { static [System.Data.IDbConnection] CreateConnection([hashtable]$ht) { Throw [System.NotImplementedException]::new("ProviderBase.CreateConnection must be overloaded!") } -} \ No newline at end of file +} diff --git a/SimplySql/Providers/MySql/BouncyCastle.Crypto.dll b/SimplySql/Providers/MySql/BouncyCastle.Crypto.dll new file mode 100644 index 0000000..05036dd Binary files /dev/null and b/SimplySql/Providers/MySql/BouncyCastle.Crypto.dll differ diff --git a/SimplySql/Providers/MySql/Google.Protobuf.dll b/SimplySql/Providers/MySql/Google.Protobuf.dll index 6ea720d..77b93c7 100644 Binary files a/SimplySql/Providers/MySql/Google.Protobuf.dll and b/SimplySql/Providers/MySql/Google.Protobuf.dll differ diff --git a/SimplySql/Providers/MySql/K4os.Compression.LZ4.Streams.dll b/SimplySql/Providers/MySql/K4os.Compression.LZ4.Streams.dll new file mode 100644 index 0000000..7377c03 Binary files /dev/null and b/SimplySql/Providers/MySql/K4os.Compression.LZ4.Streams.dll differ diff --git a/SimplySql/Providers/MySql/MySql.Data.dll b/SimplySql/Providers/MySql/MySql.Data.dll index 669149a..2c4e544 100644 Binary files a/SimplySql/Providers/MySql/MySql.Data.dll and b/SimplySql/Providers/MySql/MySql.Data.dll differ diff --git a/SimplySql/Providers/MySql/System.Memory.dll b/SimplySql/Providers/MySql/System.Memory.dll new file mode 100644 index 0000000..953a9d2 Binary files /dev/null and b/SimplySql/Providers/MySql/System.Memory.dll differ diff --git a/SimplySql/Providers/MySql/Ubiety.Dns.Core.dll b/SimplySql/Providers/MySql/Ubiety.Dns.Core.dll new file mode 100644 index 0000000..b10ecf2 Binary files /dev/null and b/SimplySql/Providers/MySql/Ubiety.Dns.Core.dll differ diff --git a/SimplySql/Providers/MySql/ZstdNet.dll b/SimplySql/Providers/MySql/ZstdNet.dll new file mode 100644 index 0000000..6f68449 Binary files /dev/null and b/SimplySql/Providers/MySql/ZstdNet.dll differ diff --git a/SimplySql/Providers/MySql/config.ps1 b/SimplySql/Providers/MySql/config.ps1 index dc6492f..6ae5447 100644 --- a/SimplySql/Providers/MySql/config.ps1 +++ b/SimplySql/Providers/MySql/config.ps1 @@ -1,108 +1,109 @@ -#Load Up My Sql libraries -Add-Type -Path "$PSScriptRoot\MySql.Data.dll" - -#Provider Class -. "$PSScriptRoot\provider.ps1" - -#Open Cmdlet -Function Open-MySqlConnection { - <# - .Synopsis - Open a connection to a MySql Database. - - .Description - Open a connection to a MySql Database. - - MySql (MySql.Data) - MySql Managed Data Access @ https://dev.mysql.com/downloads/ - .NET Provider @ https://www.nuget.org/packages/mysql.Data/6.9.9 - - .Parameter ConnectionName - The name to associate with the newly created connection. - This connection will be used with other cmdlets when specifying - -ConnectionName . If you don't specify one, it will be - set to the default. - - .Parameter ConnectionString - Specifies a provider specific connectionstring to be used. - - .Parameter CommandTimeout - The default command timeout to be used for all commands executed against this connection. - - .Parameter Server - The Server for the connection. - - .Parameter Database - Database name. - - .Parameter Port - Port to connect on, if different from default (3306). - - .Parameter UserName - User to authenticate as. (deprecated, use -Credential) - - .Parameter Password - Password for the user. (deprecated, use -Credential) - - .Parameter SSLMode - None: Do not use SSL. - Required: Always use SSL. Deny connection if server does not support SSL. Do not perform server certificate validation. - VerifyCA: Always use SSL. Validate server SSL certificate, but different host name mismatch. - VerifyFull: Always use SSL and perform full certificate validation. - - #> - [CmdletBinding(DefaultParameterSetName="default")] - Param([Parameter(ValueFromPipelineByPropertyName)][Alias("cn")][string]$ConnectionName = "default" - , [Parameter(ValueFromPipelineByPropertyName)][int]$CommandTimeout = 30 - , [Parameter(ValueFromPipelineByPropertyName, ParameterSetName="default", Position=0)] - [Parameter(ValueFromPipelineByPropertyName, ParameterSetName="userpass", Position=0)][string]$Server = "localhost" - , [Parameter(ValueFromPipelineByPropertyName, ParameterSetName="default", Position=1)] - [Parameter(ValueFromPipelineByPropertyName, ParameterSetName="userpass", Position=1)][string]$Database = "mysql" - , [Parameter(ValueFromPipelineByPropertyName, ParameterSetName="default")] - [Parameter(ValueFromPipelineByPropertyName, ParameterSetName="userpass")][int]$Port = 3306 - , [Parameter(Mandatory, ValueFromPipelineByPropertyName, ParameterSetName="default")][pscredential]$Credential - , [Parameter(Mandatory, ValueFromPipelineByPropertyName, ParameterSetName="userpass")][string]$UserName - , [Parameter(Mandatory, ValueFromPipelineByPropertyName, ParameterSetName="userpass")][string]$Password - , [Parameter(ValueFromPipeline, ParameterSetName="default")] - [Parameter(ValueFromPipeline, ParameterSetName="userpass")] - [ValidateSet("None","Required","VerifyCA","VerifyFull")][string]$SSLMode = "None" - , [Parameter(Mandatory, ValueFromPipelineByPropertyName, ParameterSetName="Conn")][string]$ConnectionString) - - If($Script:Connections.ContainsKey($ConnectionName)) { Close-SqlConnection $ConnectionName } - - $sb = [MySql.Data.MySqlClient.MySqlConnectionStringBuilder]::new() - - If($PSCmdlet.ParameterSetName -eq "Conn") { $conn = [MySql.Data.MySqlClient.MySqlConnection]::new($ConnectionString) } - Else { - $sb.Server = $Server - $sb.Database = $Database - If($Port) { $sb.Port = $Port } - If($Credential) { - $sb.UserID = $Credential.UserName - $sb.Password = $Credential.GetNetworkCredential().Password - } - Else { - Write-Warning "You are using -UserName and -Password, these options are deprecated and will be removed in the future. Please consider using -Credential." - $sb.UserId = $UserName - $sb.Password = $Password - } - - $sb.UseAffectedRows = $true - $sb.AllowUserVariables = $true - $sb.SslMode = $SSLMode - - $conn = [MySql.Data.MySqlClient.MySqlConnection]::new($sb.ConnectionString) - $sb.Clear() - $sb = $null - Remove-Variable sb - } - - Try { $conn.Open() } - Catch { - $conn.Dispose() - Throw $_ - } - $Script:Connections.$ConnectionName = [MySqlProvider]::new($ConnectionName, $CommandTimeout, $conn) -} - +#Load Up My Sql libraries + +Add-Type -Path "$PSScriptRoot\MySql.Data.dll" + +#Provider Class +. "$PSScriptRoot\provider.ps1" + +#Open Cmdlet +Function Open-MySqlConnection { + <# + .Synopsis + Open a connection to a MySql Database. + + .Description + Open a connection to a MySql Database. + + MySql (MySql.Data) + MySql Managed Data Access @ https://dev.mysql.com/downloads/ + .NET Provider @ https://www.nuget.org/packages/mysql.Data/6.9.9 + + .Parameter ConnectionName + The name to associate with the newly created connection. + This connection will be used with other cmdlets when specifying + -ConnectionName . If you don't specify one, it will be + set to the default. + + .Parameter ConnectionString + Specifies a provider specific connectionstring to be used. + + .Parameter CommandTimeout + The default command timeout to be used for all commands executed against this connection. + + .Parameter Server + The Server for the connection. + + .Parameter Database + Database name. + + .Parameter Port + Port to connect on, if different from default (3306). + + .Parameter UserName + User to authenticate as. (deprecated, use -Credential) + + .Parameter Password + Password for the user. (deprecated, use -Credential) + + .Parameter SSLMode + None: Do not use SSL. + Required: Always use SSL. Deny connection if server does not support SSL. Do not perform server certificate validation. + VerifyCA: Always use SSL. Validate server SSL certificate, but different host name mismatch. + VerifyFull: Always use SSL and perform full certificate validation. + + #> + [CmdletBinding(DefaultParameterSetName="default")] + Param([Parameter(ValueFromPipelineByPropertyName)][Alias("cn")][string]$ConnectionName = "default" + , [Parameter(ValueFromPipelineByPropertyName)][int]$CommandTimeout = 30 + , [Parameter(ValueFromPipelineByPropertyName, ParameterSetName="default", Position=0)] + [Parameter(ValueFromPipelineByPropertyName, ParameterSetName="userpass", Position=0)][string]$Server = "localhost" + , [Parameter(ValueFromPipelineByPropertyName, ParameterSetName="default", Position=1)] + [Parameter(ValueFromPipelineByPropertyName, ParameterSetName="userpass", Position=1)][string]$Database = "mysql" + , [Parameter(ValueFromPipelineByPropertyName, ParameterSetName="default")] + [Parameter(ValueFromPipelineByPropertyName, ParameterSetName="userpass")][int]$Port = 3306 + , [Parameter(Mandatory, ValueFromPipelineByPropertyName, ParameterSetName="default")][pscredential]$Credential + , [Parameter(Mandatory, ValueFromPipelineByPropertyName, ParameterSetName="userpass")][string]$UserName + , [Parameter(Mandatory, ValueFromPipelineByPropertyName, ParameterSetName="userpass")][string]$Password + , [Parameter(ValueFromPipeline, ParameterSetName="default")] + [Parameter(ValueFromPipeline, ParameterSetName="userpass")] + [ValidateSet("None","Required","VerifyCA","VerifyFull")][string]$SSLMode = "None" + , [Parameter(Mandatory, ValueFromPipelineByPropertyName, ParameterSetName="Conn")][string]$ConnectionString) + + If($Script:Connections.ContainsKey($ConnectionName)) { Close-SqlConnection $ConnectionName } + + $sb = [MySql.Data.MySqlClient.MySqlConnectionStringBuilder]::new() + + If($PSCmdlet.ParameterSetName -eq "Conn") { $conn = [MySql.Data.MySqlClient.MySqlConnection]::new($ConnectionString) } + Else { + $sb.Server = $Server + $sb.Database = $Database + If($Port) { $sb.Port = $Port } + If($Credential) { + $sb.UserID = $Credential.UserName + $sb.Password = $Credential.GetNetworkCredential().Password + } + Else { + Write-Warning "You are using -UserName and -Password, these options are deprecated and will be removed in the future. Please consider using -Credential." + $sb.UserId = $UserName + $sb.Password = $Password + } + + $sb.UseAffectedRows = $true + $sb.AllowUserVariables = $true + $sb.SslMode = $SSLMode + + $conn = [MySql.Data.MySqlClient.MySqlConnection]::new($sb.ConnectionString) + $sb.Clear() + $sb = $null + Remove-Variable sb + } + + Try { $conn.Open() } + Catch { + $conn.Dispose() + Throw $_ + } + $Script:Connections.$ConnectionName = [MySqlProvider]::new($ConnectionName, $CommandTimeout, $conn) +} + Export-ModuleMember -Function Open-MySqlConnection \ No newline at end of file diff --git a/SimplySql/Providers/MySql/provider.ps1 b/SimplySql/Providers/MySql/provider.ps1 index 5dad937..87f60a5 100644 --- a/SimplySql/Providers/MySql/provider.ps1 +++ b/SimplySql/Providers/MySql/provider.ps1 @@ -1,131 +1,130 @@ -Class MySqlProvider : ProviderBase { - - MySqlProvider([string]$ConnectionName - , [int]$CommandTimeout - , [MySql.Data.MySqlClient.MySqlConnection]$Connection) { - - $this.ConnectionName = $ConnectionName - $this.CommandTimeout = $CommandTimeout - $this.Connection = $Connection - - $messages = $this.Messages - $handler = {Param($sender, [MySql.Data.MySqlClient.MySqlInfoMessageEventArgs]$e) - $messages.Enqueue(([SqlMessage]@{Received=(Get-Date); Message=$e.Message})) - }.GetNewClosure() - - $this.Connection.add_InfoMessage([MySql.Data.MySqlClient.MySqlInfoMessageEventHandler]$handler) - } - - [string] ProviderType() { return "MySql" } - - [PSCustomObject] ConnectionInfo() { - return [PSCustomObject]@{ - ConnectionName = $this.ConnectionName - ProviderType = $this.ProviderType() - ConnectionState = $this.Connection.State - ConnectionString = $this.Connection.ConnectionString - ServerVersion = $this.Connection.ServerVersion - DataSource = $this.Connection.DataSource - Database = $this.Connection.Database - CommandTimeout = $this.CommandTimeout - HasTransaction = $this.HasTransaction() - } - } - - [System.Data.DataSet] GetDataSet([System.Data.IDbCommand]$cmd, [Boolean]$ProviderTypes) { - $ds = [System.Data.DataSet]::new() - $da = [MySql.Data.MySqlClient.MySqlDataAdapter]::new($cmd) - if ($ProviderTypes) { - $da.ReturnProviderSpecificTypes = $true - } - Try { - $da.Fill($ds) - return $ds - } - Catch { Throw $_ } - Finally { $da.dispose() } - } - - [void] ChangeDatabase([string]$DatabaseName) { $this.Connection.ChangeDatabase($DatabaseName) } - - [long] BulkLoad([System.Data.IDataReader]$DataReader - , [string]$DestinationTable - , [hashtable]$ColumnMap = @{} - , [int]$BatchSize - , [int]$BatchTimeout - , [ScriptBlock]$Notify) { - - $BatchSize -= $BatchSize % 10 - $SchemaMap = @() - [long]$batchIteration = 0 - [int]$ord = 0 - $DataReader.GetSchemaTable().Rows | Sort-Object ColumnOrdinal | ForEach-Object { $SchemaMap += [PSCustomObject]@{Ordinal = $ord; SrcName = $_["ColumnName"]; DestName = $_["ColumnName"]}; $ord += 1} - - If($ColumnMap -and $ColumnMap.Count -gt 0) { - $SchemaMap = $SchemaMap | - Where-Object SrcName -In $ColumnMap.Keys | - ForEach-Object { $_.DestName = $ColumnMap[$_.SrcName]; $_ } - } - - [string[]]$DestNames = $SchemaMap | Select-Object -ExpandProperty DestName - [string]$ValueSql = (1..10 | ForEach-Object { "(@Param" + (($SchemaMap | ForEach-Object Ordinal) -join ("_{0}, @Param" -f $_)) + ("_{0})" -f $_) }) -join ", " - [string]$InsertSql = 'INSERT INTO {0} (`{1}`) VALUES {2}' -f $DestinationTable, ($DestNames -join '`, `'), $ValueSql - - $bulkCmd = $this.GetCommand($InsertSql, -1, @{}) - $bulkCmd.Prepare() - Try { - $bulkCmd.Transaction = $this.Connection.BeginTransaction() - $sw = [System.Diagnostics.Stopwatch]::StartNew() - While($DataReader.Read()) { - $batchIteration += 1 - $r = $batchIteration % 10 - If($r -eq 0) { $r = 10 } - If($batchIteration -le 10) { - $SchemaMap.ForEach({ - $p = 'Param{0}_{1}' -f $_.Ordinal, $r - $bulkCmd.Parameters.AddWithValue($p, $DataReader.GetValue($_.Ordinal)) - }) - } - Else { - $SchemaMap.ForEach({ - $p = 'Param{0}_{1}' -f $_.Ordinal, $r - $bulkCmd.Parameters[$p].Value = $DataReader.GetValue($_.Ordinal) - }) - } - - If($r -eq 10) { $null = $bulkCmd.ExecuteNonQuery() } - If($sw.Elapsed.TotalSeconds -gt $BatchTimeout) { Throw [System.TimeoutException]::new(("Batch took longer than {0} seconds to complete." -f $BatchTimeout)) } - - If($batchIteration % $BatchSize -eq 0) { - $bulkCmd.Transaction.Commit() - $bulkCmd.Transaction.Dispose() - If($Notify) { $Notify.Invoke($batchIteration) } - $bulkCmd.Transaction = $this.Connection.BeginTransaction() - $sw.Restart() - } - } - $r = $batchIteration % 10 - If($r -eq 0) { $r = 10 } - If($r -ne 10) { - [string]$ValueSql = ((1..$r) | ForEach-Object { "(@Param" + (($SchemaMap | ForEach-Object Ordinal) -join ("_{0}, @Param" -f $_)) + ("_{0})" -f $_) }) -join ", " - [string]$InsertSql = 'INSERT INTO {0} (`{1}`) VALUES {2}' -f $DestinationTable, ($DestNames -join '`, `'), $ValueSql - $bulkCmd.CommandText = $InsertSql - $bulkCmd.Prepare() - [int]$mr = $r * $SchemaMap.Count - While($bulkCmd.Parameters.Count -gt $mr){ $null = $bulkCmd.Parameters.RemoveAt($mr) } - $null = $bulkCmd.ExecuteNonQuery() - } - - $bulkCmd.Transaction.Commit() - $bulkCmd.Transaction.Dispose() - $bulkCmd.Transaction = $null - } - Finally { - If($bulkCmd.Transaction) { $bulkCmd.Transaction.Dispose() } - $bulkCmd.Dispose() - $DataReader.Close() - $DataReader.Dispose() - } - Return $batchIteration - } +Class MySqlProvider : ProviderBase { + + MySqlProvider([string]$ConnectionName + , [int]$CommandTimeout + , [MySql.Data.MySqlClient.MySqlConnection]$Connection) { + + $this.ConnectionName = $ConnectionName + $this.CommandTimeout = $CommandTimeout + $this.Connection = $Connection + + $messages = $this.Messages + $handler = {Param($sender, [MySql.Data.MySqlClient.MySqlInfoMessageEventArgs]$e) + $messages.Enqueue(([SqlMessage]@{Received=(Get-Date); Message=$e.Message})) + }.GetNewClosure() + + $this.Connection.add_InfoMessage([MySql.Data.MySqlClient.MySqlInfoMessageEventHandler]$handler) + } + + [string] ProviderType() { return "MySql" } + + [PSCustomObject] ConnectionInfo() { + return [PSCustomObject]@{ + ConnectionName = $this.ConnectionName + ProviderType = $this.ProviderType() + ConnectionState = $this.Connection.State + ConnectionString = $this.Connection.ConnectionString + ServerVersion = $this.Connection.ServerVersion + DataSource = $this.Connection.DataSource + Database = $this.Connection.Database + CommandTimeout = $this.CommandTimeout + HasTransaction = $this.HasTransaction() + } + } + + [System.Data.DataSet] GetDataSet([System.Data.IDbCommand]$cmd, [Boolean]$ProviderTypes) { + $ds = [System.Data.DataSet]::new() + $da = [MySql.Data.MySqlClient.MySqlDataAdapter]::new($cmd) + if ($ProviderTypes) { + $da.ReturnProviderSpecificTypes = $true + } + Try { + $da.Fill($ds) + return $ds + } + Catch { Throw $_ } + Finally { $da.dispose() } + } + + [void] ChangeDatabase([string]$DatabaseName) { $this.Connection.ChangeDatabase($DatabaseName) } + + [long] BulkLoad([System.Data.IDataReader]$DataReader + , [string]$DestinationTable + , [hashtable]$ColumnMap = @{} + , [int]$BatchSize + , [int]$BatchTimeout + , [ScriptBlock]$Notify) { + + $BatchSize -= $BatchSize % 10 + $SchemaMap = @() + [long]$batchIteration = 0 + [int]$ord = 0 + $DataReader.GetSchemaTable().Rows | Sort-Object ColumnOrdinal | ForEach-Object { $SchemaMap += [PSCustomObject]@{Ordinal = $ord; SrcName = $_["ColumnName"]; DestName = $_["ColumnName"]}; $ord += 1} + + If($ColumnMap -and $ColumnMap.Count -gt 0) { + $SchemaMap = $SchemaMap | + Where-Object SrcName -In $ColumnMap.Keys | + ForEach-Object { $_.DestName = $ColumnMap[$_.SrcName]; $_ } + } + + [string[]]$DestNames = $SchemaMap | Select-Object -ExpandProperty DestName + [string]$ValueSql = (1..10 | ForEach-Object { "(@Param" + (($SchemaMap | ForEach-Object Ordinal) -join ("_{0}, @Param" -f $_)) + ("_{0})" -f $_) }) -join ", " + [string]$InsertSql = 'INSERT INTO {0} (`{1}`) VALUES {2}' -f $DestinationTable, ($DestNames -join '`, `'), $ValueSql + $bulkCmd = $this.GetCommand($InsertSql, -1, @{}) + Try { + $bulkCmd.Transaction = $this.Connection.BeginTransaction() + $sw = [System.Diagnostics.Stopwatch]::StartNew() + While($DataReader.Read()) { + $batchIteration += 1 + $r = $batchIteration % 10 + If($r -eq 0) { $r = 10 } + If($batchIteration -le 10) { + $SchemaMap.ForEach({ + $p = 'Param{0}_{1}' -f $_.Ordinal, $r + $bulkCmd.Parameters.AddWithValue($p, $DataReader.GetValue($_.Ordinal)) + }) + if($batchIteration -eq 10) { $bulkCmd.Prepare() } + } + Else { + $SchemaMap.ForEach({ + $p = 'Param{0}_{1}' -f $_.Ordinal, $r + $bulkCmd.Parameters[$p].Value = $DataReader.GetValue($_.Ordinal) + }) + } + + If($r -eq 10) { $null = $bulkCmd.ExecuteNonQuery() } + If($sw.Elapsed.TotalSeconds -gt $BatchTimeout) { Throw [System.TimeoutException]::new(("Batch took longer than {0} seconds to complete." -f $BatchTimeout)) } + + If($batchIteration % $BatchSize -eq 0) { + $bulkCmd.Transaction.Commit() + $bulkCmd.Transaction.Dispose() + If($Notify) { $Notify.Invoke($batchIteration) } + $bulkCmd.Transaction = $this.Connection.BeginTransaction() + $sw.Restart() + } + } + $r = $batchIteration % 10 + If($r -eq 0) { $r = 10 } + If($r -ne 10) { + [string]$ValueSql = ((1..$r) | ForEach-Object { "(@Param" + (($SchemaMap | ForEach-Object Ordinal) -join ("_{0}, @Param" -f $_)) + ("_{0})" -f $_) }) -join ", " + [string]$InsertSql = 'INSERT INTO {0} (`{1}`) VALUES {2}' -f $DestinationTable, ($DestNames -join '`, `'), $ValueSql + $bulkCmd.CommandText = $InsertSql + $bulkCmd.Prepare() + [int]$mr = $r * $SchemaMap.Count + While($bulkCmd.Parameters.Count -gt $mr){ $null = $bulkCmd.Parameters.RemoveAt($mr) } + $null = $bulkCmd.ExecuteNonQuery() + } + + $bulkCmd.Transaction.Commit() + $bulkCmd.Transaction.Dispose() + $bulkCmd.Transaction = $null + } + Finally { + If($bulkCmd.Transaction) { $bulkCmd.Transaction.Dispose() } + $bulkCmd.Dispose() + $DataReader.Close() + $DataReader.Dispose() + } + Return $batchIteration + } } \ No newline at end of file diff --git a/SimplySql/SimplySql.psd1 b/SimplySql/SimplySql.psd1 index b99b934..595831b 100644 Binary files a/SimplySql/SimplySql.psd1 and b/SimplySql/SimplySql.psd1 differ diff --git a/VersionHistory.md b/VersionHistory.md index d5fb0c8..5b48355 100644 --- a/VersionHistory.md +++ b/VersionHistory.md @@ -1,5 +1,9 @@ # Version History +### 1.9.0 +* Updated classes to use `::new()` constructor. thanks @joalcorn +* Updated MySql provider to use new library (8.0.28). thanks @twerthi + ### 1.8.0 * Minor Update, enhancing progress notifications for Invoke-SqlBulkCopy, you can now specify -NotifyAction and pass in a scriptblock ### 1.7.0