diff --git a/Frends.MicrosoftSQL.ExecuteQueryToFile/CHANGELOG.md b/Frends.MicrosoftSQL.ExecuteQueryToFile/CHANGELOG.md index 4a398c7..2fe47cc 100644 --- a/Frends.MicrosoftSQL.ExecuteQueryToFile/CHANGELOG.md +++ b/Frends.MicrosoftSQL.ExecuteQueryToFile/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## [2.3.0] - 2026-01-30 +### Fixed +- Fixed an issue that was causing problems with Frends processes' cleanup and assembly unloading. + ## [2.2.0] - 2026-01-22 ### Changed diff --git a/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile/Definitions/CsvFileWriter.cs b/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile/Definitions/CsvFileWriter.cs index 3ec19e4..3088149 100644 --- a/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile/Definitions/CsvFileWriter.cs +++ b/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile/Definitions/CsvFileWriter.cs @@ -15,7 +15,7 @@ namespace Frends.MicrosoftSQL.ExecuteQueryToFile.Definitions; -internal class CsvFileWriter +internal class CsvFileWriter : IAsyncDisposable { internal CsvFileWriter(SqlCommand sqlCommand, Input input, CsvOptions options) { @@ -30,31 +30,27 @@ internal CsvFileWriter(SqlCommand sqlCommand, Input input, CsvOptions options) private CsvOptions Options { get; set; } - public async Task SaveQueryToCSV(CancellationToken cancellationToken) + public async ValueTask DisposeAsync() { - var output = 0; - var encoding = GetEncoding(Options.FileEncoding, Options.EnableBom, Options.EncodingInString); - - using (var writer = new StreamWriter(Input.OutputFilePath, false, encoding)) - using (var csvFile = CreateCsvWriter(Options.GetFieldDelimiterAsString(), writer)) - { - writer.NewLine = Options.GetLineBreakAsString(); - - var reader = await SqlCommand.ExecuteReaderAsync(cancellationToken).ConfigureAwait(false); - output = DataReaderToCsv(reader, csvFile, Options, cancellationToken); + if (SqlCommand != null) await SqlCommand.DisposeAsync(); + } - csvFile.Flush(); - } + public async Task SaveQueryToCsv(CancellationToken cancellationToken) + { + var encoding = GetEncoding(Options.FileEncoding, Options.EnableBom, Options.EncodingInString); + await using var writer = new StreamWriter(Input.OutputFilePath, false, encoding); + await using var csvFile = CreateCsvWriter(Options.GetFieldDelimiterAsString(), writer); + writer.NewLine = Options.GetLineBreakAsString(); + var reader = await SqlCommand.ExecuteReaderAsync(cancellationToken).ConfigureAwait(false); + var output = DataReaderToCsv(reader, csvFile, Options, cancellationToken); + await csvFile.FlushAsync().ConfigureAwait(false); return new Result(output, Input.OutputFilePath, Path.GetFileName(Input.OutputFilePath)); } private static CsvWriter CreateCsvWriter(string delimiter, TextWriter writer) { - var csvOptions = new CsvConfiguration(CultureInfo.InvariantCulture) - { - Delimiter = delimiter, - }; + var csvOptions = new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = delimiter, }; return new CsvWriter(writer, csvOptions); } @@ -63,8 +59,8 @@ private static string FormatDbHeader(string header, bool forceSpecialFormatting) { if (!forceSpecialFormatting) return header; - // First part of regex removes all non-alphanumeric ('_' also allowed) chars from the whole string. - // Second part removed any leading numbers or underscoress. + // The first part of regex removes all non-alphanumeric ('_' also allowed) chars from the whole string. + // The second part removed any leading numbers or underscores. var rgx = new Regex("[^a-zA-Z0-9_-]|^[0-9_]+"); header = rgx.Replace(header, string.Empty); @@ -132,7 +128,7 @@ private static int DataReaderToCsv( CsvOptions options, CancellationToken cancellationToken) { - // Write header and remember column indexes to include. + // Write a header and remember column indexes to include it. var columnIndexesToInclude = new List(); for (var i = 0; i < reader.FieldCount; i++) @@ -180,7 +176,10 @@ private static int DataReaderToCsv( return count; } - private static Encoding GetEncoding(FileEncoding optionsFileEncoding, bool optionsEnableBom, string optionsEncodingInString) + private static Encoding GetEncoding( + FileEncoding optionsFileEncoding, + bool optionsEnableBom, + string optionsEncodingInString) { return optionsFileEncoding switch { diff --git a/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile/Enums/FileEncoding.cs b/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile/Enums/FileEncoding.cs index 7a5d692..21b066b 100644 --- a/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile/Enums/FileEncoding.cs +++ b/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile/Enums/FileEncoding.cs @@ -1,16 +1,16 @@ -namespace Frends.MicrosoftSQL.ExecuteQueryToFile.Enums; - -#pragma warning disable CS1591 // Self-explanatory -/// -/// File encoding used to encode the file. -/// -public enum FileEncoding -{ - UTF8, - ANSI, - ASCII, - Unicode, - Other, -} - -#pragma warning restore CS1591 // Self-explanatory +namespace Frends.MicrosoftSQL.ExecuteQueryToFile.Enums; + +#pragma warning disable CS1591 // Self-explanatory +/// +/// File encoding used to encode the file. +/// +public enum FileEncoding +{ + UTF8, + ANSI, + ASCII, + Unicode, + Other, +} + +#pragma warning restore CS1591 // Self-explanatory diff --git a/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile/Enums/ReturnFormat.cs b/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile/Enums/ReturnFormat.cs index 1f2749e..909d941 100644 --- a/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile/Enums/ReturnFormat.cs +++ b/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile/Enums/ReturnFormat.cs @@ -1,12 +1,12 @@ -namespace Frends.MicrosoftSQL.ExecuteQueryToFile.Enums; - -#pragma warning disable CS1591 // Self-explanatory -/// -/// Enumeration for output format. -/// -public enum ReturnFormat -{ - CSV, -} - -#pragma warning restore CS1591 // Self-explanatory +namespace Frends.MicrosoftSQL.ExecuteQueryToFile.Enums; + +#pragma warning disable CS1591 // Self-explanatory +/// +/// Enumeration for output format. +/// +public enum ReturnFormat +{ + CSV, +} + +#pragma warning restore CS1591 // Self-explanatory diff --git a/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile.cs b/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile.cs index 1e5d353..2c51983 100644 --- a/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile.cs +++ b/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile.cs @@ -1,6 +1,4 @@ -namespace Frends.MicrosoftSQL.ExecuteQueryToFile; - -using System; +using System; using System.ComponentModel; using System.Data; using System.Threading; @@ -9,6 +7,8 @@ using Frends.MicrosoftSQL.ExecuteQueryToFile.Enums; using Microsoft.Data.SqlClient; +namespace Frends.MicrosoftSQL.ExecuteQueryToFile; + /// /// Main class of the Task. /// @@ -22,45 +22,49 @@ public static class MicrosoftSQL /// Options parameters. /// Cancellation token given by Frends. /// Object { int EntriesWritten, string Path, string FileName } - public static async Task ExecuteQueryToFile([PropertyTab] Input input, [PropertyTab] Options options, CancellationToken cancellationToken) + public static async Task ExecuteQueryToFile( + [PropertyTab] Input input, + [PropertyTab] Options options, + CancellationToken cancellationToken) { Result result = new(); - using (var sqlConnection = new SqlConnection(input.ConnectionString)) - { - await sqlConnection.OpenAsync(cancellationToken); - using var command = sqlConnection.CreateCommand(); - command.CommandTimeout = options.TimeoutSeconds; - command.CommandText = input.Query; - command.CommandType = CommandType.Text; + await using var sqlConnection = new SqlConnection(input.ConnectionString); + await sqlConnection.OpenAsync(cancellationToken).ConfigureAwait(false); + + await using var command = sqlConnection.CreateCommand(); + command.CommandTimeout = options.TimeoutSeconds; + command.CommandText = input.Query; + command.CommandType = CommandType.Text; - if (input.QueryParameters != null) + if (input.QueryParameters != null) + { + foreach (var parameter in input.QueryParameters) { - foreach (var parameter in input.QueryParameters) - { - if (parameter.Value is null) - parameter.Value = DBNull.Value; + parameter.Value ??= DBNull.Value; - if (parameter.SqlDataType is SqlDataTypes.Auto) - { - command.Parameters.AddWithValue(parameterName: parameter.Name, value: parameter.Value); - } - else - { - var sqlDbType = (SqlDbType)Enum.Parse(typeof(SqlDbType), parameter.SqlDataType.ToString()); - var commandParameter = command.Parameters.Add(parameter.Name, sqlDbType); - commandParameter.Value = parameter.Value; - } + if (parameter.SqlDataType is SqlDataTypes.Auto) + { + command.Parameters.AddWithValue(parameterName: parameter.Name, value: parameter.Value); + } + else + { + var sqlDbType = (SqlDbType)Enum.Parse(typeof(SqlDbType), parameter.SqlDataType.ToString()); + var commandParameter = command.Parameters.Add(parameter.Name, sqlDbType); + commandParameter.Value = parameter.Value; } } + } + + switch (options.ReturnFormat) + { + case ReturnFormat.CSV: + { + await using var csvWriter = new CsvFileWriter(command, input, options.CsvOptions); + result = await csvWriter.SaveQueryToCsv(cancellationToken).ConfigureAwait(false); - switch (options.ReturnFormat) - { - case ReturnFormat.CSV: - var csvWriter = new CsvFileWriter(command, input, options.CsvOptions); - result = await csvWriter.SaveQueryToCSV(cancellationToken); break; - } + } } return result; diff --git a/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile.csproj b/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile.csproj index 74f7074..19115b6 100644 --- a/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile.csproj +++ b/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile/Frends.MicrosoftSQL.ExecuteQueryToFile.csproj @@ -3,7 +3,7 @@ net6.0 Latest - 2.2.0 + 2.3.0 Frends Frends Frends