diff --git a/LaaProductionWeb/LaaProductionWeb.Data/FluentSQL.cs b/LaaProductionWeb/LaaProductionWeb.Data/FluentSQL.cs new file mode 100644 index 00000000..dfaacfa0 --- /dev/null +++ b/LaaProductionWeb/LaaProductionWeb.Data/FluentSQL.cs @@ -0,0 +1,108 @@ +namespace LaaProductionWeb.Data +{ + using LaaProductionWeb.Data.Interfaces; + + using System; + using System.Collections.Generic; + using System.Data; + using System.Data.SqlClient; + using System.Linq; + + public class FluentSQL : IFluentSQL + { + private readonly string connectionString; + + public FluentSQL(string connectionString) + { + var connectionStringBuilder = new SqlConnectionStringBuilder(connectionString); + + this.connectionString = connectionStringBuilder.ToString(); + } + + public FluentSQLCommand CreateCommand(string commandText) + => new FluentSQLCommand(this, commandText); + + internal int ExecuteNonQuery(FluentSQLCommand command) + { + command.ThrowIfNull(); + + var rowsAffected = 0; + + using (var sqlConnection = new SqlConnection(this.connectionString)) + { + sqlConnection.OpenWithErrorHandling(); + + using (var sqlCommand = sqlConnection.CreateCommand()) + { + sqlCommand.CommandText = command.CommandText; + + sqlCommand.Parameters.AddRange(command.Parameters); + + rowsAffected = sqlCommand.ExecuteNonQuery(); + } + } + + return rowsAffected; + } + + internal IEnumerable ExecuteReader(FluentSQLCommand command, Func expression) + { + command.ThrowIfNull(); + expression.ThrowIfNull(); + + using (var sqlConnection = new SqlConnection(this.connectionString)) + { + sqlConnection.OpenWithErrorHandling(); + + using (var sqlCommand = sqlConnection.CreateCommand()) + { + sqlCommand.CommandText = command.CommandText; + + sqlCommand.Parameters.AddRange(command.Parameters); + + using (FluentSQLReader sqlReader = sqlCommand.ExecuteReader(CommandBehavior.SequentialAccess)) + { + while (sqlReader.Read()) + { + yield return expression(sqlReader); + } + } + } + } + } + + internal T ExecuteScalar(FluentSQLCommand command, Func expression) + { + command.ThrowIfNull(); + expression.ThrowIfNull(); + + var scalarResult = default(T); + + using (var sqlConnection = new SqlConnection(this.connectionString)) + { + sqlConnection.OpenWithErrorHandling(); + + using (var sqlCommand = sqlConnection.CreateCommand()) + { + sqlCommand.CommandText = command.CommandText; + + sqlCommand.Parameters.AddRange(command.Parameters); + + var scalarObject = sqlCommand.ExecuteScalar(); + + if (scalarObject is T scalarValue) + { + scalarResult = scalarValue; + } + } + } + + return scalarResult; + } + + internal T FirstOrDefault(FluentSQLCommand command, Func expression) + => this + .ExecuteReader(command, expression) + .FirstOrDefault(); + } +} diff --git a/LaaProductionWeb/LaaProductionWeb.Data/FluentSQLCommand.cs b/LaaProductionWeb/LaaProductionWeb.Data/FluentSQLCommand.cs new file mode 100644 index 00000000..e0badde2 --- /dev/null +++ b/LaaProductionWeb/LaaProductionWeb.Data/FluentSQLCommand.cs @@ -0,0 +1,65 @@ +namespace LaaProductionWeb.Data +{ + using LaaProductionWeb.Data.Interfaces; + + using System; + using System.Collections.Generic; + using System.Data.SqlClient; + using System.Linq; + + public class FluentSQLCommand : IFluentSQLCommand + { + private readonly FluentSQL fluentSql; + private readonly ICollection parameters; + + public FluentSQLCommand(FluentSQL fluentSql, string commandText) + { + this.fluentSql = fluentSql.EnsureNotNull(); + this.CommandText = commandText.EnsureNotNullOrWhiteSpace(); + this.parameters = new List(); + } + + internal string CommandText { get; } + + internal SqlParameter[] Parameters + => this.parameters.ToArray(); + + public int ExecuteNonQuery() + => this.fluentSql.ExecuteNonQuery(this); + + public IEnumerable ExecuteReader(Func expression) + => this.fluentSql.ExecuteReader(this, expression); + + public T ExecuteScalar(Func expression) + => this.fluentSql.ExecuteScalar(this, expression); + + public T FirstOrDefault(Func expression) + => this.fluentSql.FirstOrDefault(this, expression); + + public IFluentSQLCommand SetParameter(string name, object value) + { + name.ThrowIfNullOrWhiteSpace(); + + if (value is null) + { + value = DBNull.Value; + } + + var parameter = new SqlParameter(name, value); + + this.parameters.Add(parameter); + + return this; + } + + public IFluentSQLCommand SetParameters(IEnumerable> parameters) + { + foreach (var kvp in parameters) + { + this.SetParameter(kvp.Key, kvp.Value); + } + + return this; + } + } +} diff --git a/LaaProductionWeb/LaaProductionWeb.Data/FluentSQLExtensions.cs b/LaaProductionWeb/LaaProductionWeb.Data/FluentSQLExtensions.cs new file mode 100644 index 00000000..61b59aee --- /dev/null +++ b/LaaProductionWeb/LaaProductionWeb.Data/FluentSQLExtensions.cs @@ -0,0 +1,52 @@ +namespace LaaProductionWeb.Data +{ + using System; + using System.Data.SqlClient; + using System.Runtime.CompilerServices; + + internal static class FluentSQLExtensions + { + public static T EnsureNotNull(this T value, [CallerMemberName] string memberName = "") + { + value.ThrowIfNull(memberName); + + return value; + } + + public static string EnsureNotNullOrWhiteSpace(this string value, [CallerMemberName] string memberName = "") + { + value.ThrowIfNullOrWhiteSpace(memberName); + + return value; + } + + public static void ThrowIfNull(this T value, [CallerMemberName] string memberName = "") + { + if (value == null) + { + throw new ArgumentException($"{memberName} should not be null.", memberName); + } + } + + public static void ThrowIfNullOrWhiteSpace(this string value, [CallerMemberName] string memberName = "") + { + if (string.IsNullOrWhiteSpace(value)) + { + throw new ArgumentException($"{memberName} should not be null or white space.", memberName); + } + } + + internal static void OpenWithErrorHandling(this SqlConnection sqlConnection) + { + sqlConnection.FireInfoMessageEventOnUserErrors = true; + sqlConnection.InfoMessage += SqlConnectionInfoMessage; + + sqlConnection.Open(); + } + + private static void SqlConnectionInfoMessage(object sender, SqlInfoMessageEventArgs e) + { + // TODO: Log error message to the caller or elsewhere. + } + } +} diff --git a/LaaProductionWeb/LaaProductionWeb.Data/FluentSQLReader.cs b/LaaProductionWeb/LaaProductionWeb.Data/FluentSQLReader.cs new file mode 100644 index 00000000..0610a83a --- /dev/null +++ b/LaaProductionWeb/LaaProductionWeb.Data/FluentSQLReader.cs @@ -0,0 +1,151 @@ +namespace LaaProductionWeb.Data +{ + using LaaProductionWeb.Data.Interfaces; + + using System; + using System.Data.SqlClient; + + public class FluentSQLReader : IFluentSQLReader, IDisposable + { + private readonly SqlDataReader sqlDataReader; + + private int index; + + private FluentSQLReader(SqlDataReader sqlDataReader) + => this.sqlDataReader = sqlDataReader.EnsureNotNull(); + + public void Dispose() + { + this.sqlDataReader.Close(); + this.sqlDataReader.Dispose(); + } + + public bool GetBool() + { + this.index++; + + if (!this.sqlDataReader.IsDBNull(this.index)) + { + return this.sqlDataReader.GetBoolean(this.index); + } + + return default(bool); + } + + public byte[] GetBytes() + { + this.index++; + + var bytes = default(byte[]); + + if (!this.sqlDataReader.IsDBNull(this.index)) + { + bytes = this.sqlDataReader.GetFieldValue(0); + } + + return bytes ?? Array.Empty(); + } + + public DateTime GetDate() + { + this.index++; + + if (!this.sqlDataReader.IsDBNull(this.index)) + { + return this.sqlDataReader.GetDateTime(this.index); + } + + return default(DateTime); + } + + public int GetInt() + { + this.index++; + + if (!this.sqlDataReader.IsDBNull(this.index)) + { + return this.sqlDataReader.GetInt32(this.index); + } + + return default(int); + } + + public long GetLong() + { + this.index++; + + if (!this.sqlDataReader.IsDBNull(this.index)) + { + return this.sqlDataReader.GetInt64(this.index); + } + + return default(long); + } + + public short GetSmallint() + { + this.index++; + + if (!this.sqlDataReader.IsDBNull(this.index)) + { + return this.sqlDataReader.GetInt16(this.index); + } + + return default(short); + } + + public string GetString() + { + this.index++; + + if (!this.sqlDataReader.IsDBNull(this.index)) + { + return $"{this.sqlDataReader.GetValue(this.index)}"; + } + + return default(string); + } + + public T GetValue() + { + this.index++; + + if (!this.sqlDataReader.IsDBNull(this.index)) + { + if (this.sqlDataReader.GetValue(this.index) is T value) + { + return value; + } + } + + return default(T); + } + + public object GetValue(string column) + { + column.EnsureNotNullOrWhiteSpace(); + + var colIndex = this.sqlDataReader.GetOrdinal(column); + + if (colIndex >= 0 && colIndex < this.sqlDataReader.FieldCount) + { + if (!this.sqlDataReader.IsDBNull(this.index)) + { + return this.sqlDataReader.GetValue(this.index); + } + } + + return default(object); + } + + internal bool Read() + { + this.index = -1; + + return this.sqlDataReader.Read(); + } + + public static implicit operator FluentSQLReader(SqlDataReader sqlDataReader) + => new FluentSQLReader(sqlDataReader); + } +} \ No newline at end of file diff --git a/LaaProductionWeb/LaaProductionWeb.Data/Interfaces/IFluentSQL.cs b/LaaProductionWeb/LaaProductionWeb.Data/Interfaces/IFluentSQL.cs new file mode 100644 index 00000000..4b2de335 --- /dev/null +++ b/LaaProductionWeb/LaaProductionWeb.Data/Interfaces/IFluentSQL.cs @@ -0,0 +1,7 @@ +namespace LaaProductionWeb.Data.Interfaces +{ + public interface IFluentSQL + { + FluentSQLCommand CreateCommand(string commandText); + } +} diff --git a/LaaProductionWeb/LaaProductionWeb.Data/Interfaces/IFluentSQLCommand.cs b/LaaProductionWeb/LaaProductionWeb.Data/Interfaces/IFluentSQLCommand.cs new file mode 100644 index 00000000..f44451fb --- /dev/null +++ b/LaaProductionWeb/LaaProductionWeb.Data/Interfaces/IFluentSQLCommand.cs @@ -0,0 +1,20 @@ +namespace LaaProductionWeb.Data.Interfaces +{ + using System; + using System.Collections.Generic; + + public interface IFluentSQLCommand + { + int ExecuteNonQuery(); + + IEnumerable ExecuteReader(Func expression); + + T ExecuteScalar(Func expression); + + T FirstOrDefault(Func expression); + + IFluentSQLCommand SetParameter(string name, object value); + + IFluentSQLCommand SetParameters(IEnumerable> parameters); + } +} diff --git a/LaaProductionWeb/LaaProductionWeb.Data/Interfaces/IFluentSQLReader.cs b/LaaProductionWeb/LaaProductionWeb.Data/Interfaces/IFluentSQLReader.cs new file mode 100644 index 00000000..be11cea0 --- /dev/null +++ b/LaaProductionWeb/LaaProductionWeb.Data/Interfaces/IFluentSQLReader.cs @@ -0,0 +1,25 @@ +namespace LaaProductionWeb.Data.Interfaces +{ + using System; + + public interface IFluentSQLReader + { + bool GetBool(); + + byte[] GetBytes(); + + DateTime GetDate(); + + int GetInt(); + + long GetLong(); + + short GetSmallint(); + + string GetString(); + + T GetValue(); + + object GetValue(string column); + } +} \ No newline at end of file diff --git a/LaaProductionWeb/LaaProductionWeb.Data/Interfaces/ISqlClient.cs b/LaaProductionWeb/LaaProductionWeb.Data/Interfaces/ISqlClient.cs deleted file mode 100644 index 54b314b5..00000000 --- a/LaaProductionWeb/LaaProductionWeb.Data/Interfaces/ISqlClient.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace LaaProductionWeb.Data.Interfaces -{ - using System; - using System.Collections.Generic; - using System.Data.SqlClient; - - public interface ISqlClient - { - int ExecuteNonQuery(string query, Action parameters, SqlInfoMessageEventHandler errorCallback = null); - - IEnumerable ExecuteReader(string query, Func reader, SqlInfoMessageEventHandler errorCallback = null); - - IEnumerable ExecuteReader(string query, Func reader, Action columns, SqlInfoMessageEventHandler errorCallback = null); - - IEnumerable ExecuteReader(string query, Action parameters, Func reader, SqlInfoMessageEventHandler errorCallback = null); - - IEnumerable ExecuteReader(string query, Action parameters, Func reader, Action columns, SqlInfoMessageEventHandler errorCallback = null); - - T ExecuteScalar(string query, Action parameters, SqlInfoMessageEventHandler errorCallback = null); - - T FirstOrDefault(string query, Func reader, SqlInfoMessageEventHandler errorCallback = null); - - T FirstOrDefault(string query, Action parameters, Func reader, SqlInfoMessageEventHandler errorCallback = null); - - - SQLCommand CreateCommand(string commandText); - } -} diff --git a/LaaProductionWeb/LaaProductionWeb.Data/Interfaces/ISqlParameters.cs b/LaaProductionWeb/LaaProductionWeb.Data/Interfaces/ISqlParameters.cs deleted file mode 100644 index 5f62cab9..00000000 --- a/LaaProductionWeb/LaaProductionWeb.Data/Interfaces/ISqlParameters.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace LaaProductionWeb.Data.Interfaces -{ - public interface ISqlParameters - { - ISqlParameters Add(string name, object value); - - ISqlParameters AddFile(string name, byte[] fileContent); - } -} \ No newline at end of file diff --git a/LaaProductionWeb/LaaProductionWeb.Data/Interfaces/ISqlReader.cs b/LaaProductionWeb/LaaProductionWeb.Data/Interfaces/ISqlReader.cs deleted file mode 100644 index a6fca309..00000000 --- a/LaaProductionWeb/LaaProductionWeb.Data/Interfaces/ISqlReader.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; - -namespace LaaProductionWeb.Data.Interfaces -{ - public interface ISqlReader - { - bool GetBool(int index = -1); - - byte[] GetBytes(int index = -1); - - DateTime GetDate(int index = -1); - - int GetInt(int index = -1); - - long GetLong(int index = -1); - - short GetSmallint(int index = -1); - - string GetString(int index = -1); - - T GetValue(int index = -1); - - object GetValue(string field); - } -} \ No newline at end of file diff --git a/LaaProductionWeb/LaaProductionWeb.Data/LaaProductionWeb.Data.csproj b/LaaProductionWeb/LaaProductionWeb.Data/LaaProductionWeb.Data.csproj index ed456850..e5ab81b7 100644 --- a/LaaProductionWeb/LaaProductionWeb.Data/LaaProductionWeb.Data.csproj +++ b/LaaProductionWeb/LaaProductionWeb.Data/LaaProductionWeb.Data.csproj @@ -32,29 +32,20 @@ 4 - - ..\..\..\..\..\..\..\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.extensions.dependencyinjection.abstractions\2.1.1\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll - - - - - - - - - - - - - + + + + + + - + diff --git a/LaaProductionWeb/LaaProductionWeb.Data/SQLCommand.cs b/LaaProductionWeb/LaaProductionWeb.Data/SQLCommand.cs deleted file mode 100644 index ad36f3a4..00000000 --- a/LaaProductionWeb/LaaProductionWeb.Data/SQLCommand.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace LaaProductionWeb.Data -{ - using LaaProductionWeb.Data.Interfaces; - - using System; - using System.Collections.Generic; - - public class SQLCommand - { - private readonly SqlClient sqlClient; - private readonly IDictionary parameters; - - public SQLCommand(SqlClient sqlClient, string commandText) - { - this.sqlClient = sqlClient; - this.CommandText = commandText; - this.parameters = new Dictionary(); - } - - internal string CommandText { get; } - - internal IReadOnlyDictionary Parameters - => this.parameters as IReadOnlyDictionary; - - public SQLCommand AddParameter(string name, object value) - { - this.parameters[name] = value ?? DBNull.Value; - - return this; - } - - public T FirstOrDefault(Func expression) - => this.sqlClient.FirstOrDefault(this, expression); - - public int ExecuteNonQuery() - => this.sqlClient.ExecuteNonQuery(this); - - public IEnumerable ExecuteReader(Func expression) - => this.sqlClient.ExecuteReader(this, expression); - } -} diff --git a/LaaProductionWeb/LaaProductionWeb.Data/SqlClient.cs b/LaaProductionWeb/LaaProductionWeb.Data/SqlClient.cs deleted file mode 100644 index abe94a8c..00000000 --- a/LaaProductionWeb/LaaProductionWeb.Data/SqlClient.cs +++ /dev/null @@ -1,298 +0,0 @@ -namespace LaaProductionWeb.Data -{ - using LaaProductionWeb.Data.Interfaces; - - using System; - using System.Collections.Generic; - using System.Data; - using System.Data.SqlClient; - - public class SqlClient : ISqlClient - { - private readonly string connectionString; - - public SqlClient(string connectionString) - => this.connectionString = connectionString; - - public SQLCommand CreateCommand(string commandText) - => new SQLCommand(this, commandText); - - public int ExecuteNonQuery(string query, Action parameters, SqlInfoMessageEventHandler errorCallback = null) - { - var rowsAffected = 0; - - using (var sqlConnection = new SqlConnection(this.connectionString)) - { - sqlConnection.OpenWithErrorHandling(errorCallback); - - using (var sqlCommand = sqlConnection.CreateCommand()) - { - parameters(sqlCommand.Parameters); - - sqlCommand.CommandText = query; - rowsAffected = sqlCommand.ExecuteNonQuery(); - } - } - - return rowsAffected; - } - - internal int ExecuteNonQuery(SQLCommand command) - { - var rowsAffected = 0; - - using (var sqlConnection = new SqlConnection(this.connectionString)) - { - sqlConnection.OpenWithErrorHandling(); - - using (var sqlCommand = sqlConnection.CreateCommand()) - { - sqlCommand.CommandText = command.CommandText; - - foreach (var kvp in command.Parameters) - { - sqlCommand.Parameters.Add(new SqlParameter(kvp.Key, kvp.Value)); - } - - rowsAffected = sqlCommand.ExecuteNonQuery(); - } - } - - return rowsAffected; - } - - internal IEnumerable ExecuteReader(SQLCommand command, Func expression) - { - using (var sqlConnection = new SqlConnection(this.connectionString)) - { - sqlConnection.OpenWithErrorHandling(); - - using (var sqlCommand = sqlConnection.CreateCommand()) - { - sqlCommand.CommandText = command.CommandText; - - foreach (var kvp in command.Parameters) - { - var param = sqlCommand.CreateParameter(); - param.ParameterName = kvp.Key; - param.Value = kvp.Value; - - sqlCommand.Parameters.Add(param); - } - - using (SqlReader sqlReader = sqlCommand.ExecuteReader(CommandBehavior.SequentialAccess)) - { - while (sqlReader.Read()) - { - yield return expression(sqlReader); - } - } - } - } - } - - public IEnumerable ExecuteReader(string query, Func reader, SqlInfoMessageEventHandler errorCallback = null) - { - using (var sqlConnection = new SqlConnection(this.connectionString)) - { - sqlConnection.OpenWithErrorHandling(errorCallback); - - using (var sqlCommand = sqlConnection.CreateCommand()) - { - sqlCommand.CommandText = query; - - using (SqlReader sqlReader = sqlCommand.ExecuteReader()) - { - while (sqlReader.Read()) - { - yield return reader(sqlReader); - } - } - } - } - } - - public IEnumerable ExecuteReader(string query, Action parameters, Func reader, SqlInfoMessageEventHandler errorCallback = null) - { - using (var sqlConnection = new SqlConnection(this.connectionString)) - { - sqlConnection.OpenWithErrorHandling(errorCallback); - - using (var sqlCommand = sqlConnection.CreateCommand()) - { - parameters(sqlCommand.Parameters); - - sqlCommand.CommandText = query; - - using (SqlReader sqlReader = sqlCommand.ExecuteReader()) - { - while (sqlReader.Read()) - { - yield return reader(sqlReader); - } - } - } - } - } - - public IEnumerable ExecuteReader(string query, Func reader, Action columns, SqlInfoMessageEventHandler errorCallback = null) - { - using (var sqlConnection = new SqlConnection(this.connectionString)) - { - sqlConnection.OpenWithErrorHandling(errorCallback); - - using (var sqlCommand = sqlConnection.CreateCommand()) - { - sqlCommand.CommandText = query; - - using (SqlReader sqlReader = sqlCommand.ExecuteReader()) - { - columns(sqlReader.GetColumns()); - - while (sqlReader.Read()) - { - yield return reader(sqlReader); - } - } - } - } - } - - public IEnumerable ExecuteReader(string query, Action parameters, Func reader, Action columns, SqlInfoMessageEventHandler errorCallback = null) - { - using (var sqlConnection = new SqlConnection(this.connectionString)) - { - sqlConnection.OpenWithErrorHandling(errorCallback); - - using (var sqlCommand = sqlConnection.CreateCommand()) - { - parameters(sqlCommand.Parameters); - - sqlCommand.CommandText = query; - - using (SqlReader sqlReader = sqlCommand.ExecuteReader()) - { - columns(sqlReader.GetColumns()); - - while (sqlReader.Read()) - { - yield return reader(sqlReader); - } - } - } - } - } - - public T ExecuteScalar(string query, Action parameters, SqlInfoMessageEventHandler errorCallback = null) - { - var scalarResult = default(T); - - using (var sqlConnection = new SqlConnection(this.connectionString)) - { - sqlConnection.OpenWithErrorHandling(errorCallback); - - using (var sqlCommand = sqlConnection.CreateCommand()) - { - parameters(sqlCommand.Parameters); - - sqlCommand.CommandText = query; - - var scalarObject = sqlCommand.ExecuteScalar(); - - if (scalarObject is T scalarValue) - { - scalarResult = scalarValue; - } - } - } - - return scalarResult; - } - - internal T FirstOrDefault(SQLCommand command, Func expression) - { - var firstOrDefaultResult = default(T); - - using (var sqlConnection = new SqlConnection(this.connectionString)) - { - sqlConnection.OpenWithErrorHandling(); - - using (var sqlCommand = sqlConnection.CreateCommand()) - { - sqlCommand.CommandText = command.CommandText; - - foreach (var kvp in command.Parameters) - { - var param = sqlCommand.CreateParameter(); - param.ParameterName = kvp.Key; - param.Value = kvp.Value; - - sqlCommand.Parameters.Add(param); - } - - using (SqlReader sqlReader = sqlCommand.ExecuteReader(CommandBehavior.SequentialAccess)) - { - if (sqlReader.Read()) - { - firstOrDefaultResult = expression(sqlReader); - } - } - } - } - - return firstOrDefaultResult; - } - - public T FirstOrDefault(string query, Func reader, SqlInfoMessageEventHandler errorCallback = null) - { - var firstOrDefaultResult = default(T); - - using (var sqlConnection = new SqlConnection(this.connectionString)) - { - sqlConnection.OpenWithErrorHandling(errorCallback); - - using (var sqlCommand = sqlConnection.CreateCommand()) - { - sqlCommand.CommandText = query; - - using (SqlReader sqlReader = sqlCommand.ExecuteReader(CommandBehavior.SequentialAccess)) - { - if (sqlReader.Read()) - { - firstOrDefaultResult = reader(sqlReader); - } - } - } - } - - return firstOrDefaultResult; - } - - public T FirstOrDefault(string query, Action parameters, Func reader, SqlInfoMessageEventHandler errorCallback = null) - { - var firstOrDefaultResult = default(T); - - using (var sqlConnection = new SqlConnection(this.connectionString)) - { - sqlConnection.OpenWithErrorHandling(errorCallback); - - using (var sqlCommand = sqlConnection.CreateCommand()) - { - parameters(sqlCommand.Parameters); - - sqlCommand.CommandText = query; - - using (SqlReader sqlReader = sqlCommand.ExecuteReader(CommandBehavior.SequentialAccess)) - { - if (sqlReader.Read()) - { - firstOrDefaultResult = reader(sqlReader); - } - } - } - } - - return firstOrDefaultResult; - } - } -} diff --git a/LaaProductionWeb/LaaProductionWeb.Data/SqlClientExtensions.cs b/LaaProductionWeb/LaaProductionWeb.Data/SqlClientExtensions.cs deleted file mode 100644 index 66404a4e..00000000 --- a/LaaProductionWeb/LaaProductionWeb.Data/SqlClientExtensions.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace LaaProductionWeb.Data -{ - using LaaProductionWeb.Data.Interfaces; - - using Microsoft.Extensions.DependencyInjection; - - using System.Data.SqlClient; - using System.Diagnostics; - using System.Threading.Tasks; - - public static class SqlClientExtensions - { - public static IServiceCollection AddDbContext(this IServiceCollection services, string connectionString) - { - services.AddTransient(_ => new SqlClient(connectionString)); - - return services; - } - - internal static void OpenWithErrorHandling(this SqlConnection sqlConnection, SqlInfoMessageEventHandler messageHandler = null) - { - sqlConnection.FireInfoMessageEventOnUserErrors = true; - sqlConnection.InfoMessage += SqlConnectionInfoMessage; - - if (messageHandler != null) - { - sqlConnection.InfoMessage += messageHandler; - } - - sqlConnection.Open(); - } - - internal static async Task OpenWithErrorHandlingAsync(this SqlConnection sqlConnection, SqlInfoMessageEventHandler messageHandler = null) - { - sqlConnection.FireInfoMessageEventOnUserErrors = true; - sqlConnection.InfoMessage += SqlConnectionInfoMessage; - - if (messageHandler != null) - { - sqlConnection.InfoMessage += messageHandler; - } - - await sqlConnection.OpenAsync(); - } - - internal static void SqlConnectionInfoMessage(object sender, SqlInfoMessageEventArgs e) - { - Debug.Write(e); - } - } -} diff --git a/LaaProductionWeb/LaaProductionWeb.Data/SqlParameters.cs b/LaaProductionWeb/LaaProductionWeb.Data/SqlParameters.cs deleted file mode 100644 index a7dc8b7f..00000000 --- a/LaaProductionWeb/LaaProductionWeb.Data/SqlParameters.cs +++ /dev/null @@ -1,44 +0,0 @@ -namespace LaaProductionWeb.Data -{ - using LaaProductionWeb.Data.Interfaces; - - using System; - using System.Data; - using System.Data.SqlClient; - - public class SqlParameters : ISqlParameters - { - private readonly SqlParameterCollection parameters; - - private SqlParameters(SqlParameterCollection parameters) - => this.parameters = parameters; - - public ISqlParameters Add(string name, object value) - { - this.parameters.Add(new SqlParameter(name, value ?? DBNull.Value)); - - return this; - } - - public ISqlParameters AddFile(string name, byte[] fileContent) - { - var sqlParameter = new SqlParameter(name, SqlDbType.VarBinary); - - if (fileContent is null) - { - sqlParameter.Value = DBNull.Value; - } - else - { - sqlParameter.Value = fileContent; - } - - this.parameters.Add(sqlParameter); - - return this; - } - - public static implicit operator SqlParameters(SqlParameterCollection sqlParameterCollection) - => new SqlParameters(sqlParameterCollection); - } -} diff --git a/LaaProductionWeb/LaaProductionWeb.Data/SqlReader.cs b/LaaProductionWeb/LaaProductionWeb.Data/SqlReader.cs deleted file mode 100644 index 833283a8..00000000 --- a/LaaProductionWeb/LaaProductionWeb.Data/SqlReader.cs +++ /dev/null @@ -1,197 +0,0 @@ -namespace LaaProductionWeb.Data -{ - using LaaProductionWeb.Data.Interfaces; - - using System; - using System.Collections.Generic; - using System.Data.SqlClient; - using System.Linq; - using System.Threading.Tasks; - - public class SqlReader : ISqlReader, IDisposable - { - private readonly SqlDataReader sqlDataReader; - private readonly IDictionary columns; - - private int column; - - private SqlReader(SqlDataReader sqlDataReader) - { - this.sqlDataReader = sqlDataReader; - this.columns = new Dictionary(); - - var columnsCount = this.sqlDataReader.FieldCount; - var columns = new string[columnsCount]; - - for (int i = 0; i < columnsCount; i++) - { - var columnName = this.sqlDataReader.GetName(i); - this.columns[columnName] = i; - } - } - - public void Dispose() - { - this.sqlDataReader.Close(); - this.sqlDataReader.Dispose(); - } - - public bool GetBool(int index = -1) - { - if (index < 0) - { - index = this.column++; - } - - if (!this.sqlDataReader.IsDBNull(index)) - { - return this.sqlDataReader.GetBoolean(index); - } - - return default(bool); - } - - public byte[] GetBytes(int index = -1) - { - var bytes = default(byte[]); - - if (index < 0) - { - index = this.column++; - } - - if (!this.sqlDataReader.IsDBNull(index)) - { - bytes = this.sqlDataReader.GetFieldValue(0); - } - - return bytes ?? Array.Empty(); - } - - internal string[] GetColumns() - => this.columns.Keys.ToArray(); - - public DateTime GetDate(int index = -1) - { - if (index < 0) - { - index = this.column++; - } - - if (!this.sqlDataReader.IsDBNull(index)) - { - return this.sqlDataReader.GetDateTime(index); - } - - return default(DateTime); - } - - public int GetInt(int index = -1) - { - if (index < 0) - { - index = this.column++; - } - - if (!this.sqlDataReader.IsDBNull(index)) - { - return this.sqlDataReader.GetInt32(index); - } - - return default(int); - } - - public long GetLong(int index = -1) - { - if (index < 0) - { - index = this.column++; - } - - if (!this.sqlDataReader.IsDBNull(index)) - { - return this.sqlDataReader.GetInt64(index); - } - - return default(long); - } - - public string GetString(int index = -1) - { - if (index < 0) - { - index = this.column++; - } - - if (!this.sqlDataReader.IsDBNull(index)) - { - return $"{this.sqlDataReader.GetValue(index)}"; - } - - return default(string); - } - - public T GetValue(int index = -1) - { - if (index < 0) - { - index = this.column++; - } - - if (!this.sqlDataReader.IsDBNull(index)) - { - if (this.sqlDataReader.GetValue(index) is T value) - { - return value; - } - } - - return default(T); - } - - internal bool Read() - { - this.column = 0; - - return this.sqlDataReader.Read(); - } - - internal Task ReadAsync() - { - this.column = 0; - - return this.sqlDataReader.ReadAsync(); - } - - public object GetValue(string field) - { - if (this.columns.TryGetValue($"{field}", out int index)) - { - if (!this.sqlDataReader.IsDBNull(index)) - { - return this.sqlDataReader.GetValue(index); - } - } - - return default(object); - } - - public short GetSmallint(int index = -1) - { - if (index < 0) - { - index = this.column++; - } - - if (!this.sqlDataReader.IsDBNull(index)) - { - return this.sqlDataReader.GetInt16(index); - } - - return default(short); - } - - public static implicit operator SqlReader(SqlDataReader sqlDataReader) - => new SqlReader(sqlDataReader); - } -} \ No newline at end of file diff --git a/LaaProductionWeb/LaaProductionWeb.Data/app.config b/LaaProductionWeb/LaaProductionWeb.Data/app.config index 488caa33..bd072565 100644 --- a/LaaProductionWeb/LaaProductionWeb.Data/app.config +++ b/LaaProductionWeb/LaaProductionWeb.Data/app.config @@ -8,4 +8,7 @@ - + + + + diff --git a/LaaProductionWeb/LaaProductionWeb.Services/AccountService.cs b/LaaProductionWeb/LaaProductionWeb.Services/AccountService.cs index ee915bd9..ede6a7f6 100644 --- a/LaaProductionWeb/LaaProductionWeb.Services/AccountService.cs +++ b/LaaProductionWeb/LaaProductionWeb.Services/AccountService.cs @@ -11,9 +11,9 @@ public class AccountService : IAccountService { - private readonly ISqlClient sqlClient; + private readonly IFluentSQL sqlClient; - public AccountService(ISqlClient sqlClient) + public AccountService(IFluentSQL sqlClient) => this.sqlClient = sqlClient; public Employee FindEmployee(short userId) @@ -22,7 +22,7 @@ SELECT [Vorname] + ' ' + [Name] FROM [Mitarbeiter] WHERE [MitarbeiterNr] = @{nameof(userId)}") - .AddParameter(nameof(userId), userId) + .SetParameter(nameof(userId), userId) .FirstOrDefault(x => new Employee { Name = x.GetString().Trim(), @@ -31,7 +31,7 @@ SELECT DISTINCT [Recht] FROM [MitarbeiterRechte] WHERE [MitarbeiterNr] = @{nameof(userId)}") - .AddParameter(nameof(userId), userId) + .SetParameter(nameof(userId), userId) .ExecuteReader(p => p.GetString()) }); @@ -47,21 +47,21 @@ WHERE [U].[Benutzername] = @{nameof(username)} AND [U].[PasswordHash] = @{nameof(password)} AND [SF].[AppId] = @{nameof(appId)}") - .AddParameter(nameof(username), username) - .AddParameter(nameof(password), password) - .AddParameter(nameof(appId), appId) + .SetParameter(nameof(username), username) + .SetParameter(nameof(password), password) + .SetParameter(nameof(appId), appId) .ExecuteReader(x => x.GetString()); public short Login(string username, string password) - => this.sqlClient.FirstOrDefault($@" - SELECT TOP 1 [MitarbeiterNr] - FROM [Mitarbeiter] - WHERE [Benutzername] LIKE @{nameof(username)} - AND [PasswordHash] LIKE @{nameof(password)}", - parameters => parameters - .Add(nameof(username), username) - .Add(nameof(password), password), - reader => reader.GetSmallint()); + => this.sqlClient + .CreateCommand($@" + SELECT TOP 1 [MitarbeiterNr] + FROM [Mitarbeiter] + WHERE [Benutzername] LIKE @{nameof(username)} + AND [PasswordHash] LIKE @{nameof(password)}") + .SetParameter(nameof(username), username) + .SetParameter(nameof(password), password) + .FirstOrDefault(reader => reader.GetSmallint()); public int ResetPassword(string username) => this.sqlClient @@ -69,7 +69,7 @@ UPDATE [Mitarbeiter] SET [PasswordHash] = NULL WHERE [Benutzername] = @{nameof(username)}") - .AddParameter(nameof(username), username) + .SetParameter(nameof(username), username) .ExecuteNonQuery(); public int ResetPassword(string username, string password) @@ -78,8 +78,8 @@ UPDATE [Mitarbeiter] SET [PasswordHash] = @{nameof(password)} WHERE [Benutzername] = @{nameof(username)}") - .AddParameter(nameof(username), username) - .AddParameter(nameof(password), password) + .SetParameter(nameof(username), username) + .SetParameter(nameof(password), password) .ExecuteNonQuery(); } diff --git a/LaaProductionWeb/LaaProductionWeb.Services/ApprovalsService.cs b/LaaProductionWeb/LaaProductionWeb.Services/ApprovalsService.cs index 40c2e8ed..03ae4d90 100644 --- a/LaaProductionWeb/LaaProductionWeb.Services/ApprovalsService.cs +++ b/LaaProductionWeb/LaaProductionWeb.Services/ApprovalsService.cs @@ -6,57 +6,57 @@ public class ApprovalsService : IApprovalsService { - private readonly ISqlClient sqlClient; + private readonly IFluentSQL fluentSQL; - public ApprovalsService(ISqlClient sqlClient) - => this.sqlClient = sqlClient; + public ApprovalsService(IFluentSQL fluentSQL) + => this.fluentSQL = fluentSQL; public Result Add(ProductionApproval approval) { var message = string.Empty; - var rowsAffected = this.sqlClient.ExecuteNonQuery($@" - INSERT INTO [ProductionSkipAndLifeTimeInfo] ( - [OrderNumber] - , [PcbId] - , [SkipRadioParametersCheck] - , [OverrideFwCheck] - , [OverrideLutCheck] - , [RequiredLifeTimeYearsAssembly] - , [RequiredLifeTimeYearsShipping] - , [KitronProductionDate] - , [MaxDrainedBatteryLoadPercent] - , [MaxStorageMonths] - , [ApprovalDate] - , [ApproverName] - , [ApprovalComment]) - VALUES (@{nameof(approval.OrderNr)} - , @{nameof(approval.PcbId)} - , @{nameof(approval.SkipRadioCheck)} - , @{nameof(approval.OverrideFwCheck)} - , @{nameof(approval.OverrideLutCheck)} - , @{nameof(approval.RequiredLifeTimeYearsAssembly)} - , @{nameof(approval.RequiredLifeTimeYearsShipping)} - , @{nameof(approval.KitronProductionDate)} - , @{nameof(approval.MaxDrainedBatteryLoadPercent)} - , @{nameof(approval.MaxStorageMonths)} - , @{nameof(approval.ApprovalDate)} - , @{nameof(approval.ApproverName)} - , @{nameof(approval.ApprovalComment)})", - parameters => parameters - .Add(nameof(approval.OrderNr), approval.OrderNr) - .Add(nameof(approval.PcbId), approval.PcbId) - .Add(nameof(approval.SkipRadioCheck), approval.SkipRadioCheck) - .Add(nameof(approval.OverrideFwCheck), approval.OverrideFwCheck) - .Add(nameof(approval.OverrideLutCheck), approval.OverrideLutCheck) - .Add(nameof(approval.RequiredLifeTimeYearsAssembly), approval.RequiredLifeTimeYearsAssembly) - .Add(nameof(approval.RequiredLifeTimeYearsShipping), approval.RequiredLifeTimeYearsShipping) - .Add(nameof(approval.KitronProductionDate), approval.KitronProductionDate) - .Add(nameof(approval.MaxDrainedBatteryLoadPercent), approval.MaxDrainedBatteryLoadPercent) - .Add(nameof(approval.MaxStorageMonths), approval.MaxStorageMonths) - .Add(nameof(approval.ApprovalDate), approval.ApprovalDate) - .Add(nameof(approval.ApproverName), approval.ApproverName) - .Add(nameof(approval.ApprovalComment), approval.ApprovalComment), - errorCallback: (s, args) => message = args.Message); + var rowsAffected = this.fluentSQL + .CreateCommand($@" + INSERT INTO [ProductionSkipAndLifeTimeInfo] ( + [OrderNumber] + , [PcbId] + , [SkipRadioParametersCheck] + , [OverrideFwCheck] + , [OverrideLutCheck] + , [RequiredLifeTimeYearsAssembly] + , [RequiredLifeTimeYearsShipping] + , [KitronProductionDate] + , [MaxDrainedBatteryLoadPercent] + , [MaxStorageMonths] + , [ApprovalDate] + , [ApproverName] + , [ApprovalComment]) + VALUES (@{nameof(approval.OrderNr)} + , @{nameof(approval.PcbId)} + , @{nameof(approval.SkipRadioCheck)} + , @{nameof(approval.OverrideFwCheck)} + , @{nameof(approval.OverrideLutCheck)} + , @{nameof(approval.RequiredLifeTimeYearsAssembly)} + , @{nameof(approval.RequiredLifeTimeYearsShipping)} + , @{nameof(approval.KitronProductionDate)} + , @{nameof(approval.MaxDrainedBatteryLoadPercent)} + , @{nameof(approval.MaxStorageMonths)} + , @{nameof(approval.ApprovalDate)} + , @{nameof(approval.ApproverName)} + , @{nameof(approval.ApprovalComment)})") + .SetParameter(nameof(approval.OrderNr), approval.OrderNr) + .SetParameter(nameof(approval.PcbId), approval.PcbId) + .SetParameter(nameof(approval.SkipRadioCheck), approval.SkipRadioCheck) + .SetParameter(nameof(approval.OverrideFwCheck), approval.OverrideFwCheck) + .SetParameter(nameof(approval.OverrideLutCheck), approval.OverrideLutCheck) + .SetParameter(nameof(approval.RequiredLifeTimeYearsAssembly), approval.RequiredLifeTimeYearsAssembly) + .SetParameter(nameof(approval.RequiredLifeTimeYearsShipping), approval.RequiredLifeTimeYearsShipping) + .SetParameter(nameof(approval.KitronProductionDate), approval.KitronProductionDate) + .SetParameter(nameof(approval.MaxDrainedBatteryLoadPercent), approval.MaxDrainedBatteryLoadPercent) + .SetParameter(nameof(approval.MaxStorageMonths), approval.MaxStorageMonths) + .SetParameter(nameof(approval.ApprovalDate), approval.ApprovalDate) + .SetParameter(nameof(approval.ApproverName), approval.ApproverName) + .SetParameter(nameof(approval.ApprovalComment), approval.ApprovalComment) + .ExecuteNonQuery(); Result result = rowsAffected == 1; diff --git a/LaaProductionWeb/LaaProductionWeb.Services/LaaProductionWeb.Services.csproj b/LaaProductionWeb/LaaProductionWeb.Services/LaaProductionWeb.Services.csproj index 65e120d9..eb907a51 100644 --- a/LaaProductionWeb/LaaProductionWeb.Services/LaaProductionWeb.Services.csproj +++ b/LaaProductionWeb/LaaProductionWeb.Services/LaaProductionWeb.Services.csproj @@ -116,7 +116,6 @@ - diff --git a/LaaProductionWeb/LaaProductionWeb.Services/OrdersService.cs b/LaaProductionWeb/LaaProductionWeb.Services/OrdersService.cs index 0aa541d9..64c00118 100644 --- a/LaaProductionWeb/LaaProductionWeb.Services/OrdersService.cs +++ b/LaaProductionWeb/LaaProductionWeb.Services/OrdersService.cs @@ -6,15 +6,15 @@ public class OrdersService : IOrdersService { - private readonly ISqlClient sqlClient; + private readonly IFluentSQL sqlClient; - public OrdersService(ISqlClient sqlClient) + public OrdersService(IFluentSQL sqlClient) => this.sqlClient = sqlClient; public OrdersFoundModel FindOrders(string search) { - var ordersFound = this.sqlClient.ExecuteReader( - query: $@" + var ordersFound = this.sqlClient + .CreateCommand($@" SELECT DISTINCT [AlleAuftragPositionen].[AuftragNr] -- 0 , [AlleAuftragPositionen].[FertigungsauftragNr] -- 1 @@ -25,12 +25,12 @@ AND [AlleAuftragPositionen].[AuftragNr] LIKE @{nameof(search)} ORDER BY [AlleAuftragPositionen].[AuftragNr] , [AlleAuftragPositionen].[FertigungsauftragNr] - , [Kunde].[Name]", - parameters: parameters => parameters.Add(nameof(search), $"%{search}%"), - reader: reader => new OrderInfoModel + , [Kunde].[Name]") + .SetParameter(nameof(search), $"%{search}%") + .ExecuteReader(reader => new OrderInfoModel { - OrderNr = reader.GetValue(), - ProductionOrderNr = reader.GetValue(), + OrderNr = reader.GetInt(), + ProductionOrderNr = reader.GetInt(), Customer = reader.GetString(), }); @@ -39,31 +39,32 @@ public OrderPositions FindPositions(string orderNr) { - var positionsFound = this.sqlClient.ExecuteReader( - query: $@" + var positionsFound = this.sqlClient + .CreateCommand($@" SELECT DISTINCT [AlleAuftragPositionen].[PositionNr] -- 0 FROM [AlleAuftragPositionen] WHERE [AlleAuftragPositionen].[AuftragNr] = @{nameof(orderNr)} OR [AlleAuftragPositionen].[FertigungsauftragNr] = @{nameof(orderNr)} - ORDER BY [AlleAuftragPositionen].[PositionNr]", - parameters: parameters => parameters.Add(nameof(orderNr), orderNr), - reader: reader => (int)reader.GetValue(0)); + ORDER BY [AlleAuftragPositionen].[PositionNr]") + .SetParameter(nameof(orderNr), orderNr) + .ExecuteReader(reader => (int)reader.GetSmallint()); return new OrderPositions(positionsFound); } public ProductionOrders FindProductionOrders(string productionNr) { - var ordersFound = this.sqlClient.ExecuteReader($@" + var ordersFound = this.sqlClient + .CreateCommand($@" SELECT DISTINCT [AlleAuftragPositionen].[FertigungsauftragNr] -- 1 FROM [AlleAuftragPositionen] WHERE [AlleAuftragPositionen].[Versand_Ist_datum] IS NOT NULL AND [AlleAuftragPositionen].[AuftragNr] LIKE @{nameof(productionNr)} - ORDER BY [AlleAuftragPositionen].[FertigungsauftragNr]", - parameters => parameters.Add(nameof(productionNr), $"{productionNr}%"), - reader => reader.GetValue()); + ORDER BY [AlleAuftragPositionen].[FertigungsauftragNr]") + .SetParameter(nameof(productionNr), $"{productionNr}%") + .ExecuteReader(reader => reader.GetInt()); return new ProductionOrders(ordersFound); } diff --git a/LaaProductionWeb/LaaProductionWeb.Services/ProtocolService.cs b/LaaProductionWeb/LaaProductionWeb.Services/ProtocolService.cs index 2d371bdf..1bd049ad 100644 --- a/LaaProductionWeb/LaaProductionWeb.Services/ProtocolService.cs +++ b/LaaProductionWeb/LaaProductionWeb.Services/ProtocolService.cs @@ -12,37 +12,40 @@ public class ProtocolService : IProtocolService { - private readonly ISqlClient sqlClient; + private readonly IFluentSQL fluentSQL; - public ProtocolService(ISqlClient sqlClient) - => this.sqlClient = sqlClient; + public ProtocolService(IFluentSQL fluentSQL) + => this.fluentSQL = fluentSQL; public bool DeleteFile(int fileId) - => this.sqlClient.ExecuteScalar($@" + => this.fluentSQL + .CreateCommand($@" DELETE FROM [File] WHERE [FileId] = @{nameof(fileId)}; DELETE FROM [FilesOrders] OUTPUT [Deleted].[FileId] - WHERE [FileId] = @{nameof(fileId)};", - parameters: parameters => parameters.Add(nameof(fileId), fileId)) > 0; + WHERE [FileId] = @{nameof(fileId)};") + .SetParameter(nameof(fileId), fileId) + .ExecuteScalar(x => x.GetInt()) > 0; public string FileContent(int? fileId) { - var fileContent = this.sqlClient.FirstOrDefault( - query: $@" + var fileContent = this.fluentSQL + .CreateCommand($@" SELECT [dbo].[File].[FileContent] FROM [dbo].[File] - WHERE [dbo].[File].[FileId] = @{nameof(fileId)}", - parameters: parameters => parameters.Add(nameof(fileId), fileId), - reader: reader => reader.GetBytes(0)) ?? Array.Empty(); + WHERE [dbo].[File].[FileId] = @{nameof(fileId)}") + .SetParameter(nameof(fileId), fileId) + .FirstOrDefault(reader => reader.GetBytes()) + ?? Array.Empty(); return string.Format("data:application/pdf;base64,{0}", Convert.ToBase64String(fileContent)); } public OrderClientModel FindOrder(int orderId) { - var orderClientModel = this.sqlClient.FirstOrDefault( - query: $@" + var orderClientModel = this.fluentSQL + .CreateCommand($@" SELECT DISTINCT [APG].[AuftragNr] , [K].[KundenNr] @@ -61,32 +64,34 @@ AND [IN].[Typ] = 'GNS' JOIN [Kunde] AS [K] ON [K].[KundenNr] = [AG].[KundenNr] - WHERE [APG].[AuftragNr] = @{nameof(orderId)}", - parameters: parameters => parameters.Add(nameof(orderId), orderId), - reader: reader => new OrderClientModel + WHERE [APG].[AuftragNr] = @{nameof(orderId)}") + .SetParameter(nameof(orderId), orderId) + .FirstOrDefault(reader => new OrderClientModel { - OrderId = reader.GetValue(0), - ClientId = reader.GetValue(1), - ClientName = reader.GetString(2), - Positions = reader.GetString(3).Trim().Trim(',') + OrderId = reader.GetInt(), + ClientId = reader.GetInt(), + ClientName = reader.GetString(), + Positions = reader.GetString().Trim().Trim(',') }); if (orderClientModel != null && orderId > 0) { - orderClientModel.FileId = this.sqlClient.FirstOrDefault($@" + orderClientModel.FileId = this.fluentSQL + .CreateCommand($@" SELECT [FileId] FROM [FilesOrders] WHERE [OrderId] = @{nameof(orderId)} - AND [Usage] = 'PROTOCOL'", - parameters: parameters => parameters.Add(nameof(orderId), orderId), - reader: reader => reader.GetValue(0)); + AND [Usage] = 'PROTOCOL'") + .SetParameter(nameof(orderId), orderId) + .FirstOrDefault(reader => reader.GetValue()); } return orderClientModel ?? new OrderClientModel(); } public IEnumerable> FindOrdersById(int orderno) - => this.sqlClient.ExecuteReader($@" + => this.fluentSQL + .CreateCommand($@" SELECT DISTINCT [APG].[AuftragNr] , [K].[Name] @@ -98,15 +103,15 @@ AND [IN].[Typ] = 'GNS' JOIN [Kunde] AS [K] ON [K].[KundenNr] = [AG].[KundenNr] - WHERE [APG].[AuftragNr] LIKE @{nameof(orderno)}", - parameters: parameters => parameters.Add(nameof(orderno), $"%{orderno}%"), - reader: reader => new KeyValuePair( - key: reader.GetValue(0), - value: reader.GetString(1))); + WHERE [APG].[AuftragNr] LIKE @{nameof(orderno)}") + .SetParameter(nameof(orderno), $"%{orderno}%") + .ExecuteReader(reader => new KeyValuePair( + key: reader.GetInt(), + value: reader.GetString())); public IEnumerable> FindOrdersByClient(string clientName) - => this.sqlClient.ExecuteReader( - query: $@" + => this.fluentSQL + .CreateCommand($@" SELECT DISTINCT [APG].[AuftragNr] , [K].[Name] @@ -118,15 +123,15 @@ AND [IN].[Typ] = 'GNS' JOIN [Kunde] AS [K] ON [K].[KundenNr] = [AG].[KundenNr] - WHERE [K].[Name] LIKE @{nameof(clientName)}", - parameters: parameters => parameters.Add(nameof(clientName), $"%{clientName}%"), - reader: reader => new KeyValuePair( - key: reader.GetValue(0), - value: reader.GetString(1))); + WHERE [K].[Name] LIKE @{nameof(clientName)}") + .SetParameter(nameof(clientName), $"%{clientName}%") + .ExecuteReader(reader => new KeyValuePair( + key: reader.GetInt(), + value: reader.GetString())); public IEnumerable LoadTestStatus(int orderId) - => this.sqlClient.ExecuteReader( - query: $@" + => this.fluentSQL + .CreateCommand($@" SELECT DISTINCT [APS].[PositionNr] AS [PosNr] -- 0 , ISNULL([APS].[KundeneigeneSerienNr], [APS].[SerienNr]) AS [SerialNr] -- 1 @@ -152,44 +157,45 @@ , [DP].[Dicht] , [CRRH].[Result] ORDER BY [APS].[PositionNr] - , ISNULL([APS].[KundeneigeneSerienNr], [APS].[SerienNr])", - parameters: parameters => parameters.Add(nameof(orderId), orderId), - reader: reader => new TestStatus + , ISNULL([APS].[KundeneigeneSerienNr], [APS].[SerienNr])") + .SetParameter(nameof(orderId), orderId) + .ExecuteReader(reader => new TestStatus { - PosNr = $"{reader.GetValue(0)}", - SerialNr = reader.GetValue(1), - HeliumTest = reader.GetValue(2), - PressureTest = reader.GetValue(3), - MetroTest = this.MetrologicalValue(reader.GetValue(4)), - RadioTest = reader.GetValue(5), + PosNr = $"{reader.GetSmallint()}", + SerialNr = reader.GetString(), + HeliumTest = reader.GetValue(), + PressureTest = reader.GetValue(), + MetroTest = this.MetrologicalValue(reader.GetValue()), + RadioTest = reader.GetValue(), }); public bool OrderCompleted(int orderId) { - var sumResults = this.sqlClient.ExecuteReader($@" - SELECT CAST(CASE WHEN ISNULL([CPT].[CordonelPressureTest_Valid], 1) = 1 THEN 0 ELSE 1 END AS INT) - + CAST(CASE WHEN ISNULL([DP].[Dicht], 1) = 1 THEN 0 ELSE 1 END AS INT) - + ISNULL(MAX([APS].[StatusFertigung]) - 30, 0) - + CAST(CASE WHEN ISNULL([CRRH].[Result], 1) = 1 THEN 0 ELSE 1 END AS INT) - FROM [AuftragPositionSerienNr] AS [APS] - LEFT JOIN [Genesis_Meter] AS [GM] ON [GM].[Seriennummer] = [APS].[SerienNr] - LEFT JOIN [MapPcbIdToSerialNumber] AS [PCB] ON [PCB].[MapPcbIdToSerialNumber_SerialNumber] = [GM].[Seriennummer] - LEFT JOIN [Cordonel_Radio_RSSI_History] AS [CRRH] ON [CRRH].[RadioAdress] = [GM].[Adresse] - 10000000000 - AND [CRRH].[IsLast] = 1 - AND [CRRH].[Result] = 1 - LEFT JOIN [Druckpruefung] AS [DP] ON [DP].[FabNr] = [PCB].[MapPcbIdToSerialNumber_PcbId] - AND [DP].[Dicht] = 1 - LEFT JOIN [Cordonel_PressureTest] AS [CPT] ON [CPT].[CordonelPressureTest_PcbId] = [PCB].[MapPcbIdToSerialNumber_PcbId] - AND [CPT].[CordonelPressureTest_Valid] = 1 - WHERE [APS].[AuftragNr] = @{nameof(orderId)} - GROUP BY [APS].[PositionNr] - , [APS].[SerienNr] - , [APS].[KundeneigeneSerienNr] - , [CPT].[CordonelPressureTest_Valid] - , [DP].[Dicht] - , [CRRH].[Result]", - parameters => parameters.Add(nameof(orderId), orderId), - reader => reader.GetValue(0)) + var sumResults = this.fluentSQL + .CreateCommand($@" + SELECT CAST(CASE WHEN ISNULL([CPT].[CordonelPressureTest_Valid], 1) = 1 THEN 0 ELSE 1 END AS INT) + + CAST(CASE WHEN ISNULL([DP].[Dicht], 1) = 1 THEN 0 ELSE 1 END AS INT) + + ISNULL(MAX([APS].[StatusFertigung]) - 30, 0) + + CAST(CASE WHEN ISNULL([CRRH].[Result], 1) = 1 THEN 0 ELSE 1 END AS INT) + FROM [AuftragPositionSerienNr] AS [APS] + LEFT JOIN [Genesis_Meter] AS [GM] ON [GM].[Seriennummer] = [APS].[SerienNr] + LEFT JOIN [MapPcbIdToSerialNumber] AS [PCB] ON [PCB].[MapPcbIdToSerialNumber_SerialNumber] = [GM].[Seriennummer] + LEFT JOIN [Cordonel_Radio_RSSI_History] AS [CRRH] ON [CRRH].[RadioAdress] = [GM].[Adresse] - 10000000000 + AND [CRRH].[IsLast] = 1 + AND [CRRH].[Result] = 1 + LEFT JOIN [Druckpruefung] AS [DP] ON [DP].[FabNr] = [PCB].[MapPcbIdToSerialNumber_PcbId] + AND [DP].[Dicht] = 1 + LEFT JOIN [Cordonel_PressureTest] AS [CPT] ON [CPT].[CordonelPressureTest_PcbId] = [PCB].[MapPcbIdToSerialNumber_PcbId] + AND [CPT].[CordonelPressureTest_Valid] = 1 + WHERE [APS].[AuftragNr] = @{nameof(orderId)} + GROUP BY [APS].[PositionNr] + , [APS].[SerienNr] + , [APS].[KundeneigeneSerienNr] + , [CPT].[CordonelPressureTest_Valid] + , [DP].[Dicht] + , [CRRH].[Result]") + .SetParameter(nameof(orderId), orderId) + .ExecuteReader(reader => reader.GetInt()) .Sum(x => x); return sumResults == 0; @@ -200,8 +206,8 @@ var fileName = $"{clientId}_{orderId}.pdf"; var fileContent = this.GetBuffer(fileStream); - return this.sqlClient.ExecuteScalar( - query: $@" + return this.fluentSQL + .CreateCommand($@" INSERT INTO [dbo].[File] ( [FileName] , [FileContent]) @@ -209,11 +215,11 @@ INTO [dbo].[FilesOrders]([OrderId], [FileId], [Usage]) OUTPUT [Inserted].[FileId] VALUES (@{nameof(fileName)} - , @{nameof(fileContent)})", - parameters: parameters => parameters - .Add(nameof(orderId), orderId) - .Add(nameof(fileName), fileName) - .AddFile(nameof(fileContent), fileContent)); + , @{nameof(fileContent)})") + .SetParameter(nameof(orderId), orderId) + .SetParameter(nameof(fileName), fileName) + .SetParameter(nameof(fileContent), fileContent) + .ExecuteScalar(x => x.GetInt()); } private byte[] GetBuffer(Stream fileStream) diff --git a/LaaProductionWeb/LaaProductionWeb.Services/ReportService.cs b/LaaProductionWeb/LaaProductionWeb.Services/ReportService.cs index 0fb4d402..ca214fac 100644 --- a/LaaProductionWeb/LaaProductionWeb.Services/ReportService.cs +++ b/LaaProductionWeb/LaaProductionWeb.Services/ReportService.cs @@ -11,10 +11,10 @@ public partial class ReportService : IReportService { - private readonly ISqlClient sqlClient; + private readonly IFluentSQL fluentSQL; - public ReportService(ISqlClient sqlClient) - => this.sqlClient = sqlClient; + public ReportService(IFluentSQL fluentSQL) + => this.fluentSQL = fluentSQL; public CordonelPressureSensorModel LoadCordonelPressureSensorReport(CordonelPressureSensorModel model = null) { @@ -26,50 +26,41 @@ var where = model.Filter.Where(); var orderBy = model.Filter.OrderBy(); - model.Items = this.sqlClient.ExecuteReader($@" - SELECT [APS].[AuftragNr] AS [AuftragNr] - , [APS].[PositionNr] AS [PosNr] - , [APS].[SerienNr] AS [SerialNr] - , [APS].[KundeneigeneSerienNr] AS [CustomerSerialNr] - , [ID].[IdentNr] AS [IdentNr] - , [CPSTR].[PcbId] AS [PcbId] - , [ID].[Typ] AS [TypeI] - , [ID].[Typzusatz] AS [TypeII] - , [ID].[Nennweite] AS [Nennweite] - , [ID].[Baulaenge] AS [Baulaenge] - , [CPSTR].[AvgPressureInBar] AS [AvgPressure] - , [CPSTR].[TestPassed] AS [TestPassed] - , [CPSTR].[TestDate] AS [TestDate] - FROM [Cordonel_PressureSensor_TestResults] AS [CPSTR] - LEFT JOIN [AuftragPositionSerienNr] AS [APS] - ON [APS].[FabNr] = [CPSTR].[PcbId] - LEFT JOIN [AuftragPosition_Gesamt] AS [APG] - ON [APG].[AuftragNr] = [APS].[AuftragNr] - AND [APG].[PositionNr] = [APS].[PositionNr] - LEFT JOIN [Identnr] AS [ID] - ON [ID].[IdentNr] = [APG].[Identnr] - WHERE {where.Query} - ORDER BY {orderBy.Query}", - parameters => - { - foreach (var kvp in where.Parameters) - { - parameters.Add(kvp.Key, kvp.Value); - } - - foreach (var kvp in orderBy.Parameters) - { - parameters.Add(kvp.Key, kvp.Value); - } - }, - reader => new CordonelPressureSensorItem + model.Items = this.fluentSQL + .CreateCommand($@" + SELECT [APS].[AuftragNr] AS [AuftragNr] + , [APS].[PositionNr] AS [PosNr] + , [APS].[SerienNr] AS [SerialNr] + , [APS].[KundeneigeneSerienNr] AS [CustomerSerialNr] + , [ID].[IdentNr] AS [IdentNr] + , [CPSTR].[PcbId] AS [PcbId] + , [ID].[Typ] AS [TypeI] + , [ID].[Typzusatz] AS [TypeII] + , [ID].[Nennweite] AS [Nennweite] + , [ID].[Baulaenge] AS [Baulaenge] + , [CPSTR].[AvgPressureInBar] AS [AvgPressure] + , [CPSTR].[TestPassed] AS [TestPassed] + , [CPSTR].[TestDate] AS [TestDate] + FROM [Cordonel_PressureSensor_TestResults] AS [CPSTR] + LEFT JOIN [AuftragPositionSerienNr] AS [APS] + ON [APS].[FabNr] = [CPSTR].[PcbId] + LEFT JOIN [AuftragPosition_Gesamt] AS [APG] + ON [APG].[AuftragNr] = [APS].[AuftragNr] + AND [APG].[PositionNr] = [APS].[PositionNr] + LEFT JOIN [Identnr] AS [ID] + ON [ID].[IdentNr] = [APG].[Identnr] + WHERE {where.Query} + ORDER BY {orderBy.Query}") + .SetParameters(where.Parameters) + .SetParameters(orderBy.Parameters) + .ExecuteReader(reader => new CordonelPressureSensorItem { AuftragNr = reader.GetValue(), PosNr = reader.GetValue(), SerialNr = reader.GetValue(), CustomerSerialNr = reader.GetString(), IdentNr = reader.GetValue(), - PcbId = reader.GetValue(), + PcbId = reader.GetInt(), TypeI = reader.GetString(), TypeII = reader.GetString(), Nennweite = reader.GetValue(), @@ -92,69 +83,60 @@ var where = model.Filter.Where(); var orderBy = model.Filter.OrderBy(); - model.Items = this.sqlClient.ExecuteReader($@" - SELECT DISTINCT - [PT].[CordonelPressureTest_FertigungsAuftragsNr] AS [FertigungNr] -- 0 - , [POS].[AuftragNr] AS [AuftragNr] -- 1 - , [POS].[PositionNr] AS [PositionNr] -- 2 - , [PCB2SN].[MapPcbIdToSerialNumber_SerialNumber] AS [SerialNr] -- 3 - , [ID].[IdentNr] AS [IdentNr] -- 4 - , [PT_HE].[CordonelPressureTestHe_Id] AS [HeId] -- 5 - , [PT_HE].[CordonelPressureTestHe_TestID] AS [HeTestId] -- 6 - , [PT].[CordonelPressureTest_PcbId] AS [PcbId] -- 7 - , [ID].[Nennweite] AS [Nennweite] -- 8 - , [ID].[Baulaenge] AS [Baulaenge] -- 9 - , [ID].[Typ] AS [Typ] -- 10 - , [ID].[Druck] AS [Druck] -- 11 - , [ID].[Temperatur] AS [Temperatur] -- 12 - , [PT_HE].[CordonelPressureTestHe_LeakRate] AS [HeLakeRate] -- 13 - , [PT_HE].[CordonelPressureTestHe_TestPressure] AS [HeTestPressure] -- 14 - , [PT].[CordonelPressureTest_Valid] AS [IsValid] -- 15 - , [PT].[CordonelPressureTest_Date] AS [TestDate] -- 16 - , [PT].[CordonelPressureTest_Text] AS [Text] -- 17 - , [PT_HE].[CordonelPressureTestHe_TesterName] AS [Tester] -- 18 - FROM [Cordonel_PressureTest] AS [PT] - JOIN [Cordonel_PressureTest_He] AS [PT_HE] ON [PT_HE].[CordonelPressureTestHe_TestID] = [PT].[CordonelPressureTest_Id] - LEFT JOIN [Druckpruefung] AS [DP] ON [DP].[FabNr] = [PT].[CordonelPressureTest_PcbId] - JOIN [MapPcbIdToSerialNumber] AS [PCB2SN] ON [PCB2SN].[MapPcbIdToSerialNumber_PcbId] = [PT].[CordonelPressureTest_PcbId] - JOIN [AuftragPosition_Gesamt] AS [POS] ON [POS].[FertigungsauftragNr] = [PT].[CordonelPressureTest_FertigungsAuftragsNr] - JOIN [Identnr] AS [ID] ON [ID].[IdentNr] = [POS].[Identnr] - WHERE [CordonelPressureTest_IsDeleted] = 0 - AND {where.Query} - ORDER BY {orderBy.Query}", - parameters => + model.Items = this.fluentSQL + .CreateCommand($@" + SELECT DISTINCT + [PT].[CordonelPressureTest_FertigungsAuftragsNr] AS [FertigungNr] -- 0 + , [POS].[AuftragNr] AS [AuftragNr] -- 1 + , [POS].[PositionNr] AS [PositionNr] -- 2 + , [PCB2SN].[MapPcbIdToSerialNumber_SerialNumber] AS [SerialNr] -- 3 + , [ID].[IdentNr] AS [IdentNr] -- 4 + , [PT_HE].[CordonelPressureTestHe_Id] AS [HeId] -- 5 + , [PT_HE].[CordonelPressureTestHe_TestID] AS [HeTestId] -- 6 + , [PT].[CordonelPressureTest_PcbId] AS [PcbId] -- 7 + , [ID].[Nennweite] AS [Nennweite] -- 8 + , [ID].[Baulaenge] AS [Baulaenge] -- 9 + , [ID].[Typ] AS [Typ] -- 10 + , [ID].[Druck] AS [Druck] -- 11 + , [ID].[Temperatur] AS [Temperatur] -- 12 + , [PT_HE].[CordonelPressureTestHe_LeakRate] AS [HeLakeRate] -- 13 + , [PT_HE].[CordonelPressureTestHe_TestPressure] AS [HeTestPressure] -- 14 + , [PT].[CordonelPressureTest_Valid] AS [IsValid] -- 15 + , [PT].[CordonelPressureTest_Date] AS [TestDate] -- 16 + , [PT].[CordonelPressureTest_Text] AS [Text] -- 17 + , [PT_HE].[CordonelPressureTestHe_TesterName] AS [Tester] -- 18 + FROM [Cordonel_PressureTest] AS [PT] + JOIN [Cordonel_PressureTest_He] AS [PT_HE] ON [PT_HE].[CordonelPressureTestHe_TestID] = [PT].[CordonelPressureTest_Id] + LEFT JOIN [Druckpruefung] AS [DP] ON [DP].[FabNr] = [PT].[CordonelPressureTest_PcbId] + JOIN [MapPcbIdToSerialNumber] AS [PCB2SN] ON [PCB2SN].[MapPcbIdToSerialNumber_PcbId] = [PT].[CordonelPressureTest_PcbId] + JOIN [AuftragPosition_Gesamt] AS [POS] ON [POS].[FertigungsauftragNr] = [PT].[CordonelPressureTest_FertigungsAuftragsNr] + JOIN [Identnr] AS [ID] ON [ID].[IdentNr] = [POS].[Identnr] + WHERE [CordonelPressureTest_IsDeleted] = 0 + AND {where.Query} + ORDER BY {orderBy.Query}") + .SetParameters(where.Parameters) + .SetParameters(orderBy.Parameters) + .ExecuteReader(reader => new HeliumReportItem { - foreach (var kvp in where.Parameters) - { - parameters.Add(kvp.Key, kvp.Value); - } - - foreach (var kvp in orderBy.Parameters) - { - parameters.Add(kvp.Key, kvp.Value); - } - }, - reader => new HeliumReportItem - { - FertigungNr = reader.GetValue(0), - AuftragNr = reader.GetValue(1), - PositionNr = reader.GetValue(2), - SerialNr = reader.GetValue(3), - IdentNr = reader.GetValue(4), - HeId = reader.GetValue(5), - HeTestId = reader.GetValue(6), - PcbId = reader.GetValue(7), - Nennweite = reader.GetValue(8), - Baulaenge = reader.GetValue(9), - Typ = reader.GetString(10), - Druck = reader.GetValue(11), - Temperatur = reader.GetValue(12), - HeLakeRate = reader.GetString(13), - HeTestPressure = reader.GetString(14), - IsValid = reader.GetValue(15), - TestDate = reader.GetValue(16), - Text = reader.GetString(17), - Tester = reader.GetString(18) + FertigungNr = reader.GetInt(), + AuftragNr = reader.GetInt(), + PositionNr = reader.GetValue(), + SerialNr = reader.GetInt(), + IdentNr = reader.GetInt(), + HeId = reader.GetInt(), + HeTestId = reader.GetInt(), + PcbId = reader.GetInt(), + Nennweite = reader.GetValue(), + Baulaenge = reader.GetValue(), + Typ = reader.GetString(), + Druck = reader.GetValue(), + Temperatur = reader.GetValue(), + HeLakeRate = reader.GetString(), + HeTestPressure = reader.GetString(), + IsValid = reader.GetValue(), + TestDate = reader.GetValue(), + Text = reader.GetString(), + Tester = reader.GetString() }); return model; @@ -169,74 +151,87 @@ var where = model.Filter.Where(); var orderBy = model.Filter.OrderBy(); - var csvItems = new List(); + var csvItems = new List + { + new object[] + { + "[FertigungNr]", + "[AuftragNr]", + "[PositionNr]", + "[SerialNr]", + "[IdentNr]", + "[HeId]", + "[HeTestId]", + "[PcbId]", + "[Nennweite]", + "[Baulaenge]", + "[Typ]", + "[Druck]", + "[Temperatur]", + "[HeLakeRate]", + "[HeTestPressure]", + "[IsValid]", + "[TestDate]", + "[Text]", + "[Tester]", + } + }; var headers = Array.Empty(); - var items = this.sqlClient.ExecuteReader($@" - SELECT DISTINCT - [PT].[CordonelPressureTest_FertigungsAuftragsNr] AS [FertigungNr] -- 0 Filter - , [POS].[AuftragNr] AS [AuftragNr] -- 1 Filter - , [POS].[PositionNr] AS [PositionNr] -- 2 Filter - , [PCB2SN].[MapPcbIdToSerialNumber_SerialNumber] AS [SerialNr] -- 3 - , [ID].[IdentNr] AS [IdentNr] -- 4 Filter - , [PT_HE].[CordonelPressureTestHe_Id] AS [HeId] -- 5 - , [PT_HE].[CordonelPressureTestHe_TestID] AS [HeTestId] -- 6 - , [PT].[CordonelPressureTest_PcbId] AS [PcbId] -- 7 Filter - , [ID].[Nennweite] AS [Nennweite] -- 8 Filter - , [ID].[Baulaenge] AS [Baulaenge] -- 9 Filter - , [ID].[Typ] AS [Typ] -- 10 Filter - , [ID].[Druck] AS [Druck] -- 11 Filter - , [ID].[Temperatur] AS [Temperatur] -- 12 Filter - , [PT_HE].[CordonelPressureTestHe_LeakRate] AS [HeLakeRate] -- 13 - , [PT_HE].[CordonelPressureTestHe_TestPressure] AS [HeTestPressure] -- 14 - , [PT].[CordonelPressureTest_Valid] AS [IsValid] -- 15 Filter - , [PT].[CordonelPressureTest_Date] AS [TestDate] -- 16 Filter - , [PT].[CordonelPressureTest_Text] AS [Text] -- 17 Filter - , [PT_HE].[CordonelPressureTestHe_TesterName] AS [Tester] -- 18 - FROM [Cordonel_PressureTest] AS [PT] - JOIN [Cordonel_PressureTest_He] AS [PT_HE] ON [PT_HE].[CordonelPressureTestHe_TestID] = [PT].[CordonelPressureTest_Id] - LEFT JOIN [Druckpruefung] AS [DP] ON [DP].[FabNr] = [PT].[CordonelPressureTest_PcbId] - JOIN [MapPcbIdToSerialNumber] AS [PCB2SN] ON [PCB2SN].[MapPcbIdToSerialNumber_PcbId] = [PT].[CordonelPressureTest_PcbId] - JOIN [AuftragPosition_Gesamt] AS [POS] ON [POS].[FertigungsauftragNr] = [PT].[CordonelPressureTest_FertigungsAuftragsNr] - JOIN [Identnr] AS [ID] ON [ID].[IdentNr] = [POS].[Identnr] - WHERE [CordonelPressureTest_IsDeleted] = 0 - AND {where.Query} - ORDER BY {orderBy.Query}", - parameters => + var items = this.fluentSQL + .CreateCommand($@" + SELECT DISTINCT + [PT].[CordonelPressureTest_FertigungsAuftragsNr] AS [FertigungNr] -- 0 Filter + , [POS].[AuftragNr] AS [AuftragNr] -- 1 Filter + , [POS].[PositionNr] AS [PositionNr] -- 2 Filter + , [PCB2SN].[MapPcbIdToSerialNumber_SerialNumber] AS [SerialNr] -- 3 + , [ID].[IdentNr] AS [IdentNr] -- 4 Filter + , [PT_HE].[CordonelPressureTestHe_Id] AS [HeId] -- 5 + , [PT_HE].[CordonelPressureTestHe_TestID] AS [HeTestId] -- 6 + , [PT].[CordonelPressureTest_PcbId] AS [PcbId] -- 7 Filter + , [ID].[Nennweite] AS [Nennweite] -- 8 Filter + , [ID].[Baulaenge] AS [Baulaenge] -- 9 Filter + , [ID].[Typ] AS [Typ] -- 10 Filter + , [ID].[Druck] AS [Druck] -- 11 Filter + , [ID].[Temperatur] AS [Temperatur] -- 12 Filter + , [PT_HE].[CordonelPressureTestHe_LeakRate] AS [HeLakeRate] -- 13 + , [PT_HE].[CordonelPressureTestHe_TestPressure] AS [HeTestPressure] -- 14 + , [PT].[CordonelPressureTest_Valid] AS [IsValid] -- 15 Filter + , [PT].[CordonelPressureTest_Date] AS [TestDate] -- 16 Filter + , [PT].[CordonelPressureTest_Text] AS [Text] -- 17 Filter + , [PT_HE].[CordonelPressureTestHe_TesterName] AS [Tester] -- 18 + FROM [Cordonel_PressureTest] AS [PT] + JOIN [Cordonel_PressureTest_He] AS [PT_HE] ON [PT_HE].[CordonelPressureTestHe_TestID] = [PT].[CordonelPressureTest_Id] + LEFT JOIN [Druckpruefung] AS [DP] ON [DP].[FabNr] = [PT].[CordonelPressureTest_PcbId] + JOIN [MapPcbIdToSerialNumber] AS [PCB2SN] ON [PCB2SN].[MapPcbIdToSerialNumber_PcbId] = [PT].[CordonelPressureTest_PcbId] + JOIN [AuftragPosition_Gesamt] AS [POS] ON [POS].[FertigungsauftragNr] = [PT].[CordonelPressureTest_FertigungsAuftragsNr] + JOIN [Identnr] AS [ID] ON [ID].[IdentNr] = [POS].[Identnr] + WHERE [CordonelPressureTest_IsDeleted] = 0 + AND {where.Query} + ORDER BY {orderBy.Query}") + .SetParameters(where.Parameters) + .SetParameters(orderBy.Parameters) + .ExecuteReader(reader => new object[] { - foreach (var kvp in where.Parameters) - { - parameters.Add(kvp.Key, kvp.Value); - } - - foreach (var kvp in orderBy.Parameters) - { - parameters.Add(kvp.Key, kvp.Value); - } - }, - reader => new object[] - { - reader.GetValue(0), - reader.GetValue(1), - reader.GetValue(2), - reader.GetValue(3), - reader.GetValue(4), - reader.GetValue(5), - reader.GetValue(6), - reader.GetValue(7), - reader.GetValue(8), - reader.GetValue(9), - reader.GetString(10).Replace(',', ' '), - reader.GetValue(11), - reader.GetValue(12), - reader.GetString(13).Replace(',', '.'), - reader.GetString(14).Replace(',', ' '), - reader.GetValue(15), - $"{reader.GetValue(16):yyyy-MM-dd}", - reader.GetString(17).Replace(',', ' '), - reader.GetString(18).Replace(',', ' ') - }, - columns => csvItems.Add(columns)) - .ToList(); + reader.GetInt(), + reader.GetInt(), + reader.GetSmallint(), + reader.GetInt(), + reader.GetInt(), + reader.GetInt(), + reader.GetInt(), + reader.GetInt(), + reader.GetValue(), + reader.GetValue(), + reader.GetString().Replace(',', ' '), + reader.GetValue(), + reader.GetValue(), + reader.GetString().Replace(',', '.'), + reader.GetString().Replace(',', ' '), + reader.GetValue(), + $"{reader.GetValue():yyyy-MM-dd}", + reader.GetString().Replace(',', ' '), + reader.GetString().Replace(',', ' ') + }); csvItems.AddRange(items); @@ -247,18 +242,19 @@ } public IEnumerable LoadHeliumPressureResults(int testId) - => this.sqlClient.ExecuteReader($@" - SELECT [CordonelPressureTestTestPoints_Id] - , [CordonelPressureTest_TestPointNr] - , CAST([CordonelPressureTest_TestPointResult] AS NUMERIC(9, 8)) - FROM [Cordonel_PressureTest_TestPoints] - WHERE [CordonelPressureTest_Id] = @{nameof(testId)}", - parameters => parameters.Add(nameof(testId), testId), - reader => new HeliumPressurePoint + => this.fluentSQL + .CreateCommand($@" + SELECT [CordonelPressureTestTestPoints_Id] + , [CordonelPressureTest_TestPointNr] + , CAST([CordonelPressureTest_TestPointResult] AS NUMERIC(9, 8)) + FROM [Cordonel_PressureTest_TestPoints] + WHERE [CordonelPressureTest_Id] = @{nameof(testId)}") + .SetParameter(nameof(testId), testId) + .ExecuteReader(reader => new HeliumPressurePoint { - TestId = reader.GetValue(0), - PointNr = reader.GetValue(1), - Result = reader.GetValue(2), + TestId = reader.GetInt(), + PointNr = reader.GetInt(), + Result = reader.GetValue(), }); public KottmannReportModel LoadKottmannPressureReport(KottmannReportModel model = null) @@ -271,52 +267,43 @@ var where = model.Filter.Where(); var orderBy = model.Filter.OrderBy(); - model.Items = this.sqlClient.ExecuteReader($@" - SELECT [DP].[FertigungsauftragNr] AS [FertigungNr] - , [PCB2SN].[MapPcbIdToSerialNumber_SerialNumber] AS [SerienNr] - , [DP].[FabNr] AS [PcbId] - , [ID].[Typ] AS [Typ] - , [ID].[Nennweite] AS [Nennweite] - , [ID].[Baulaenge] AS [Baulaenge] - , [DP].[StartDruck] AS [StartDruck] - , [DP].[EndDruck] AS [EndDruck] - , [DP].[Pruefzeit] AS [Pruefzeit] - , [DP].[Dicht] AS [Dicht] - , [DP].[Datum] AS [Datum] - , [DP].[Bemerkung] AS [Bemerkung] - FROM [Druckpruefung] AS [DP] - JOIN [AuftragPosition_Gesamt] AS [POS] - ON [POS].[FertigungsauftragNr] = [DP].[FertigungsauftragNr] - JOIN [Identnr] AS [ID] - ON [ID].[IdentNr] = [POS].[Identnr] - JOIN [MapPcbIdToSerialNumber] AS [PCB2SN] - ON [PCB2SN].[MapPcbIdToSerialNumber_PcbId] = [DP].[FabNr] - AND [PCB2SN].[MapPcbIdToSerialNumber_Deleted] = 0 - AND {where.Query} - ORDER BY {orderBy.Query}", - parameters => - { - foreach (var kvp in where.Parameters) - { - parameters.Add(kvp.Key, kvp.Value); - } - - foreach (var kvp in orderBy.Parameters) - { - parameters.Add(kvp.Key, kvp.Value); - } - }, - reader => new KottmannReportItem + model.Items = this.fluentSQL + .CreateCommand($@" + SELECT [DP].[FertigungsauftragNr] AS [FertigungNr] + , [PCB2SN].[MapPcbIdToSerialNumber_SerialNumber] AS [SerienNr] + , [DP].[FabNr] AS [PcbId] + , [ID].[Typ] AS [Typ] + , [ID].[Nennweite] AS [Nennweite] + , [ID].[Baulaenge] AS [Baulaenge] + , [DP].[StartDruck] AS [StartDruck] + , [DP].[EndDruck] AS [EndDruck] + , [DP].[Pruefzeit] AS [Pruefzeit] + , [DP].[Dicht] AS [Dicht] + , [DP].[Datum] AS [Datum] + , [DP].[Bemerkung] AS [Bemerkung] + FROM [Druckpruefung] AS [DP] + JOIN [AuftragPosition_Gesamt] AS [POS] + ON [POS].[FertigungsauftragNr] = [DP].[FertigungsauftragNr] + JOIN [Identnr] AS [ID] + ON [ID].[IdentNr] = [POS].[Identnr] + JOIN [MapPcbIdToSerialNumber] AS [PCB2SN] + ON [PCB2SN].[MapPcbIdToSerialNumber_PcbId] = [DP].[FabNr] + AND [PCB2SN].[MapPcbIdToSerialNumber_Deleted] = 0 + AND {where.Query} + ORDER BY {orderBy.Query}") + .SetParameters(where.Parameters) + .SetParameters(orderBy.Parameters) + .ExecuteReader(reader => new KottmannReportItem { FertigungsNr = reader.GetValue(), - SerialNr = reader.GetValue(), - PcbId = reader.GetValue(), + SerialNr = reader.GetInt(), + PcbId = reader.GetInt(), Typ = reader.GetString(), Nennweite = reader.GetValue(), Baulaenge = reader.GetValue(), StartDruck = reader.GetValue(), EndDruck = reader.GetValue(), - DruckZeit = reader.GetValue(), + DruckZeit = reader.GetInt(), Dicht = reader.GetValue(), Datum = reader.GetValue(), Bemerkung = reader.GetValue() @@ -334,60 +321,66 @@ var where = model.Filter.Where(); var orderBy = model.Filter.OrderBy(); - var csvItems = new List(); - var headers = Array.Empty(); - var items = this.sqlClient.ExecuteReader($@" - SELECT [DP].[FertigungsauftragNr] AS [FertigungNr] - , [PCB2SN].[MapPcbIdToSerialNumber_SerialNumber] AS [SerienNr] - , [DP].[FabNr] AS [PcbId] - , [ID].[Typ] AS [Typ] - , [ID].[Nennweite] AS [Nennweite] - , [ID].[Baulaenge] AS [Baulaenge] - , [DP].[StartDruck] AS [StartDruck] - , [DP].[EndDruck] AS [EndDruck] - , [DP].[Pruefzeit] AS [Pruefzeit] - , [DP].[Dicht] AS [Dicht] - , [DP].[Datum] AS [Datum] - , [DP].[Bemerkung] AS [Bemerkung] - FROM [Druckpruefung] AS [DP] - JOIN [AuftragPosition_Gesamt] AS [POS] - ON [POS].[FertigungsauftragNr] = [DP].[FertigungsauftragNr] - JOIN [Identnr] AS [ID] - ON [ID].[IdentNr] = [POS].[Identnr] - JOIN [MapPcbIdToSerialNumber] AS [PCB2SN] - ON [PCB2SN].[MapPcbIdToSerialNumber_PcbId] = [DP].[FabNr] - AND [PCB2SN].[MapPcbIdToSerialNumber_Deleted] = 0 - AND {where.Query} - ORDER BY {orderBy.Query}", - parameters => + var csvItems = new List + { + new object[] { - foreach (var kvp in where.Parameters) - { - parameters.Add(kvp.Key, kvp.Value); - } - - foreach (var kvp in orderBy.Parameters) - { - parameters.Add(kvp.Key, kvp.Value); - } - }, - reader => new object[] + "[FertigungNr]", + "[SerienNr]", + "[PcbId]", + "[Typ]", + "[Nennweite]", + "[Baulaenge]", + "[StartDruck]", + "[EndDruck]", + "[Pruefzeit]", + "[Dicht]", + "[Datum]", + "[Bemerkung]" + } + }; + var headers = Array.Empty(); + var items = this.fluentSQL + .CreateCommand($@" + SELECT [DP].[FertigungsauftragNr] AS [FertigungNr] + , [PCB2SN].[MapPcbIdToSerialNumber_SerialNumber] AS [SerienNr] + , [DP].[FabNr] AS [PcbId] + , [ID].[Typ] AS [Typ] + , [ID].[Nennweite] AS [Nennweite] + , [ID].[Baulaenge] AS [Baulaenge] + , [DP].[StartDruck] AS [StartDruck] + , [DP].[EndDruck] AS [EndDruck] + , [DP].[Pruefzeit] AS [Pruefzeit] + , [DP].[Dicht] AS [Dicht] + , [DP].[Datum] AS [Datum] + , [DP].[Bemerkung] AS [Bemerkung] + FROM [Druckpruefung] AS [DP] + JOIN [AuftragPosition_Gesamt] AS [POS] + ON [POS].[FertigungsauftragNr] = [DP].[FertigungsauftragNr] + JOIN [Identnr] AS [ID] + ON [ID].[IdentNr] = [POS].[Identnr] + JOIN [MapPcbIdToSerialNumber] AS [PCB2SN] + ON [PCB2SN].[MapPcbIdToSerialNumber_PcbId] = [DP].[FabNr] + AND [PCB2SN].[MapPcbIdToSerialNumber_Deleted] = 0 + AND {where.Query} + ORDER BY {orderBy.Query}") + .SetParameters(where.Parameters) + .SetParameters(orderBy.Parameters) + .ExecuteReader(reader => new object[] { reader.GetValue(), - reader.GetValue(), - reader.GetValue(), + reader.GetInt(), + reader.GetInt(), reader.GetString(), reader.GetValue(), reader.GetValue(), reader.GetValue(), reader.GetValue(), - reader.GetValue(), + reader.GetInt(), reader.GetValue(), $"{reader.GetValue():yyyy-MM-dd}", reader.GetValue().Replace(',', ' ') - }, - columns => csvItems.Add(columns)) - .ToList(); + }); csvItems.AddRange(items); diff --git a/LaaProductionWeb/LaaProductionWeb.Services/ShipmentsService.cs b/LaaProductionWeb/LaaProductionWeb.Services/ShipmentsService.cs index 35cc660f..89fb4c61 100644 --- a/LaaProductionWeb/LaaProductionWeb.Services/ShipmentsService.cs +++ b/LaaProductionWeb/LaaProductionWeb.Services/ShipmentsService.cs @@ -11,13 +11,13 @@ public class ShipmentsService : IShipmentsService { - private readonly ISqlClient sqlClient; + private readonly IFluentSQL fluentSQL; - public ShipmentsService(ISqlClient sqlClient) - => this.sqlClient = sqlClient; + public ShipmentsService(IFluentSQL fluentSQL) + => this.fluentSQL = fluentSQL; public OrderScanModel DeletePalletEntry(int id) - => this.sqlClient + => this.fluentSQL .CreateCommand($@" DELETE FROM [PalettenScan] @@ -25,7 +25,7 @@ , [deleted].[PositionNr] , [deleted].[PalettenNr] WHERE [ID] = @{nameof(id)}") - .AddParameter(nameof(id), id) + .SetParameter(nameof(id), id) .FirstOrDefault(x => new OrderScanModel { OrderNr = x.GetInt(), @@ -35,23 +35,22 @@ public byte[] LoadBatchBuffer(OrderScanModel model) { - var palletLoad = this.sqlClient.ExecuteReader( - query: $@" + var palletLoad = this.fluentSQL + .CreateCommand($@" SELECT [PalettenNr] , [SerienNr] FROM [PalettenScan] WHERE [AuftragNr] = @{nameof(model.OrderNr)} AND [PositionNr] = @{nameof(model.PositionNr)} AND [PalettenNr] = @{nameof(model.PalletNr)} - ORDER BY [SerienNr]", - parameters: parameters => parameters - .Add(nameof(model.OrderNr), model.OrderNr) - .Add(nameof(model.PositionNr), model.PositionNr) - .Add(nameof(model.PalletNr), model.PalletNr), - reader: reader => string.Join(",", new string[] + ORDER BY [SerienNr]") + .SetParameter(nameof(model.OrderNr), model.OrderNr) + .SetParameter(nameof(model.PositionNr), model.PositionNr) + .SetParameter(nameof(model.PalletNr), model.PalletNr) + .ExecuteReader(reader => string.Join(",", new string[] { - reader.GetString(0), - reader.GetString(1), + reader.GetString(), + reader.GetString(), })); var csvContent = string.Join(Environment.NewLine, palletLoad); @@ -98,7 +97,7 @@ } public IEnumerable MissingItems() - => this.sqlClient + => this.fluentSQL .CreateCommand($@" DECLARE @PalletOrders TABLE([OrderNo] INT NOT NULL) INSERT INTO @PalletOrders([OrderNo]) @@ -168,21 +167,21 @@ private bool PalletNrExists(int orderNo, int? palletNo) { - var countPalletsByNo = this.sqlClient + var countPalletsByNo = this.fluentSQL .CreateCommand($@" SELECT ISNULL(COUNT(1), 0) AS [Found] FROM [PalettenScan] AS [PS] WHERE [PS].[AuftragNr] = @{nameof(orderNo)} AND [PS].[PalettenNr] = @{nameof(palletNo)}") - .AddParameter(nameof(orderNo), orderNo) - .AddParameter(nameof(palletNo), palletNo) + .SetParameter(nameof(orderNo), orderNo) + .SetParameter(nameof(palletNo), palletNo) .FirstOrDefault(x => x.GetInt()); return countPalletsByNo > 0; } private IEnumerable LoadLastPalletPositions(int orderNo) - => this.sqlClient + => this.fluentSQL .CreateCommand($@" DECLARE @palettenNr INT; @@ -215,7 +214,7 @@ AND [ps].[PositionNr] = [aap].[PositionNr] WHERE [aap].[AuftragNr] = @{nameof(orderNo)} AND [ps].[PalettenNr] = @palettenNr") - .AddParameter(nameof(orderNo), orderNo) + .SetParameter(nameof(orderNo), orderNo) .ExecuteReader(x => new PalletPosition { PositionNr = x.GetSmallint(), @@ -228,7 +227,7 @@ }); private IEnumerable LoadPalletPositions(int orderNo, int? palletNo) - => this.sqlClient + => this.fluentSQL .CreateCommand($@" SELECT DISTINCT [aap].[PositionNr] AS [Pos] @@ -255,8 +254,8 @@ AND [ps].[PositionNr] = [aap].[PositionNr] WHERE [aap].[AuftragNr] = @{nameof(orderNo)} AND [ps].[PalettenNr] = @{nameof(palletNo)}") - .AddParameter(nameof(orderNo), orderNo) - .AddParameter(nameof(palletNo), palletNo) + .SetParameter(nameof(orderNo), orderNo) + .SetParameter(nameof(palletNo), palletNo) .ExecuteReader(x => new PalletPosition { PositionNr = x.GetSmallint(), @@ -270,23 +269,23 @@ private bool SamePallet(int orderNo, int? positionNo, int? palletNo) { - var countPalletsByNo = this.sqlClient + var countPalletsByNo = this.fluentSQL .CreateCommand($@" SELECT ISNULL(COUNT(1), 0) AS [Found] FROM [PalettenScan] AS [PS] WHERE [PS].[AuftragNr] = @{nameof(orderNo)} AND [PS].[PositionNr] = @{nameof(positionNo)} AND [PS].[PalettenNr] = @{nameof(palletNo)}") - .AddParameter(nameof(orderNo), orderNo) - .AddParameter(nameof(positionNo), positionNo) - .AddParameter(nameof(palletNo), palletNo) + .SetParameter(nameof(orderNo), orderNo) + .SetParameter(nameof(positionNo), positionNo) + .SetParameter(nameof(palletNo), palletNo) .FirstOrDefault(x => x.GetInt()); return countPalletsByNo > 0; } private IEnumerable LoadLastPalletPosition(int orderNo, int? positionNo) - => this.sqlClient + => this.fluentSQL .CreateCommand($@" DECLARE @palettenNr INT; @@ -321,8 +320,8 @@ WHERE [aap].[AuftragNr] = @{nameof(orderNo)} AND ([ps].[PalettenNr] = @palettenNr OR [aap].[PositionNr] = @{nameof(positionNo)})") - .AddParameter(nameof(orderNo), orderNo) - .AddParameter(nameof(positionNo), positionNo) + .SetParameter(nameof(orderNo), orderNo) + .SetParameter(nameof(positionNo), positionNo) .ExecuteReader(x => new PalletPosition { PositionNr = x.GetSmallint(), @@ -335,7 +334,7 @@ }); private IEnumerable LoadPalletPosition(int orderNo, int? positionNo, int? palletNo) - => this.sqlClient + => this.fluentSQL .CreateCommand($@" SELECT DISTINCT [aap].[PositionNr] AS [Pos] @@ -363,9 +362,9 @@ WHERE [aap].[AuftragNr] = @{nameof(orderNo)} AND [ps].[PositionNr] = @{nameof(positionNo)} AND [ps].[PalettenNr] = @{nameof(palletNo)}") - .AddParameter(nameof(orderNo), orderNo) - .AddParameter(nameof(positionNo), positionNo) - .AddParameter(nameof(palletNo), palletNo) + .SetParameter(nameof(orderNo), orderNo) + .SetParameter(nameof(positionNo), positionNo) + .SetParameter(nameof(palletNo), palletNo) .ExecuteReader(x => new PalletPosition { PositionNr = x.GetSmallint(), @@ -378,7 +377,7 @@ }); private IEnumerable LoadPalletItems(int orderNo, int posNo, int palletNr) - => this.sqlClient + => this.fluentSQL .CreateCommand($@" SELECT [x].[Id] AS [Id] , [x].[PositionNr] AS [Pos] @@ -409,9 +408,9 @@ AS [x] ORDER BY [x].[IsScanned] DESC , [x].[CustomerSerial]") - .AddParameter(nameof(orderNo), orderNo) - .AddParameter(nameof(posNo), posNo) - .AddParameter(nameof(palletNr), palletNr) + .SetParameter(nameof(orderNo), orderNo) + .SetParameter(nameof(posNo), posNo) + .SetParameter(nameof(palletNr), palletNr) .ExecuteReader(x => new SerialNr { Id = x.GetInt(), @@ -424,8 +423,8 @@ private PalletsBatchModel LoadBatchModel(int orderNo, int? posNo, int? palletNo) { - var batchModel = this.sqlClient.FirstOrDefault( - query: $@" + var batchModel = this.fluentSQL + .CreateCommand($@" SELECT TOP 1 [AAP].[AuftragNr] , [AAP].[FertigungsauftragNr] @@ -434,14 +433,13 @@ FROM [AlleAuftragPositionen] AS [AAP] JOIN [Kunde] ON [Kunde].[KundenNr] = [AAP].[KundenNr] WHERE [AAP].[AuftragNr] = @{nameof(orderNo)} - ORDER BY [AAP].[FertigungsauftragNr] DESC", - parameters: parameters => parameters - .Add(nameof(orderNo), orderNo) - .Add(nameof(posNo), posNo), - reader: reader => new PalletsBatchModel + ORDER BY [AAP].[FertigungsauftragNr] DESC") + .SetParameter(nameof(orderNo), orderNo) + .SetParameter(nameof(posNo), posNo) + .FirstOrDefault(reader => new PalletsBatchModel { - OrderNr = reader.GetValue(), - ProductionOrderNr = reader.GetValue(), + OrderNr = reader.GetInt(), + ProductionOrderNr = reader.GetInt(), Customer = reader.GetString(), AdditionalText = reader.GetString() }); @@ -453,35 +451,36 @@ { if (model != null && model.OrderNr != null && model.OrderNr > 0) { - var pallets = this.sqlClient.ExecuteReader( - query: $@" SELECT DISTINCT - [PSI].[PalettenNr] - , CAST(CASE WHEN [PSII].[ID] IS NULL - THEN 0 - ELSE 1 - END AS BIT) - FROM [PalettenScan] AS [PSI] - LEFT JOIN [PalettenScan] AS [PSII] - ON [PSII].[ID] = [PSI].[ID] - AND [PSII].[PositionNr] = @{nameof(model.PositionNr)} - WHERE [PSI].[AuftragNr] = @{nameof(model.OrderNr)} - ORDER BY [PSI].[PalettenNr]", - parameters: parameters => parameters - .Add(nameof(model.OrderNr), model.OrderNr) - .Add(nameof(model.PositionNr), model.PositionNr), - reader: reader => new KeyValuePair( - key: (int)reader.GetValue(), + var pallets = this.fluentSQL + .CreateCommand($@" + SELECT DISTINCT + [PSI].[PalettenNr] + , CAST(CASE WHEN [PSII].[ID] IS NULL + THEN 0 + ELSE 1 + END AS BIT) + FROM [PalettenScan] AS [PSI] + LEFT JOIN [PalettenScan] AS [PSII] + ON [PSII].[ID] = [PSI].[ID] + AND [PSII].[PositionNr] = @{nameof(model.PositionNr)} + WHERE [PSI].[AuftragNr] = @{nameof(model.OrderNr)} + ORDER BY [PSI].[PalettenNr]") + .SetParameter(nameof(model.OrderNr), model.OrderNr) + .SetParameter(nameof(model.PositionNr), model.PositionNr) + .ExecuteReader(reader => new KeyValuePair( + key: reader.GetValue(), value: reader.GetValue())); model.UpdatePallets(pallets); - model.Positions = this.sqlClient.ExecuteReader( - query: $@"SELECT DISTINCT [x].[PositionNr] - FROM [AlleAuftragPositionen] AS [x] - WHERE [x].[AuftragNr] = @{nameof(model.OrderNr)} - ORDER BY [x].[PositionNr]", - parameters: parameters => parameters.Add(nameof(model.OrderNr), model.OrderNr), - reader: reader => (int)reader.GetValue()); + model.Positions = this.fluentSQL + .CreateCommand($@" + SELECT DISTINCT [x].[PositionNr] + FROM [AlleAuftragPositionen] AS [x] + WHERE [x].[AuftragNr] = @{nameof(model.OrderNr)} + ORDER BY [x].[PositionNr]") + .SetParameter(nameof(model.OrderNr), model.OrderNr) + .ExecuteReader(reader => (int)reader.GetSmallint()); } return model; @@ -525,8 +524,8 @@ } private OrderIdentity UpdateOrderIdentifiers(int? orderNr, int? positionNr, string serialNr) - => this.sqlClient.FirstOrDefault( - query: $@" + => this.fluentSQL + .CreateCommand($@" SELECT DISTINCT TOP 1 [APS].[PositionNr] , [APS].[SerienNr] @@ -534,21 +533,20 @@ FROM [AuftragPositionSerienNr] AS [APS] WHERE [APS].[AuftragNr] = @{nameof(orderNr)} AND ([APS].[PositionNr] = @{nameof(positionNr)} OR @{nameof(positionNr)} IS NULL) - AND @{nameof(serialNr)} LIKE '%' + (REPLACE(RTRIM(LTRIM([APS].[KundeneigeneSerienNr])), ' ', '')) + '%'", - parameters: parameters => parameters - .Add(nameof(orderNr), orderNr) - .Add(nameof(positionNr), positionNr) - .Add(nameof(serialNr), serialNr), - reader: reader => new OrderIdentity + AND @{nameof(serialNr)} LIKE '%' + (REPLACE(RTRIM(LTRIM([APS].[KundeneigeneSerienNr])), ' ', '')) + '%'") + .SetParameter(nameof(orderNr), orderNr) + .SetParameter(nameof(positionNr), positionNr) + .SetParameter(nameof(serialNr), serialNr) + .FirstOrDefault(reader => new OrderIdentity { OrderNr = orderNr ?? -1, - PositionNr = reader.GetValue(0), - SerialNr = reader.GetValue(1), - CustomerSerialNr = reader.GetValue(2), + PositionNr = reader.GetSmallint(), + SerialNr = reader.GetInt(), + CustomerSerialNr = reader.GetString(), }); private OrderIdentity UpdateOrderIdentifiersGenesisMetterRadioAddresses(string address) - => this.sqlClient + => this.fluentSQL .CreateCommand($@" DECLARE @serialNo NVARCHAR(50) -------------------------------------------------------------------------- @@ -569,7 +567,7 @@ , ISNULL(REPLACE(RTRIM(LTRIM([APS].[KundeneigeneSerienNr])), ' ', ''), [APS].[SerienNr]) AS [KundeneigeneSerienNr] FROM [AuftragPositionSerienNr] AS [APS] WHERE [APS].[SerienNr] = @serialNo") - .AddParameter(nameof(address), address) + .SetParameter(nameof(address), address) .FirstOrDefault(x => new OrderIdentity { OrderNr = x.GetInt(), @@ -579,7 +577,7 @@ }); private OrderIdentity UpdateOrderIdentifiersERegisterRadioAddresses(string address) - => this.sqlClient + => this.fluentSQL .CreateCommand($@" DECLARE @serialNo NVARCHAR(50) -------------------------------------------------------------------------- @@ -600,7 +598,7 @@ , ISNULL(REPLACE(RTRIM(LTRIM([APS].[KundeneigeneSerienNr])), ' ', ''), [APS].[SerienNr]) AS [KundeneigeneSerienNr] FROM [AuftragPositionSerienNr] AS [APS] WHERE [APS].[SerienNr] = @serialNo") - .AddParameter(nameof(address), address) + .SetParameter(nameof(address), address) .FirstOrDefault(x => new OrderIdentity { OrderNr = x.GetInt(), @@ -610,7 +608,8 @@ }); private int InsertPalletEntry(OrderScanModel model) - => this.sqlClient.ExecuteNonQuery($@" + => this.fluentSQL + .CreateCommand($@" INSERT INTO [PalettenScan] ( [PalettenNr] @@ -626,26 +625,26 @@ , @{nameof(model.SerialNr)} , @{nameof(model.Host)} , @{nameof(model.Place)} - , GETDATE())", - parameters => parameters - .Add(nameof(model.PalletNr), model.PalletNr) - .Add(nameof(model.OrderNr), model.OrderNr) - .Add(nameof(model.PositionNr), model.PositionNr) - .Add(nameof(model.SerialNr), model.SerialNr) - .Add(nameof(model.Host), model.Host) - .Add(nameof(model.Place), model.Place)); + , GETDATE())") + .SetParameter(nameof(model.PalletNr), model.PalletNr) + .SetParameter(nameof(model.OrderNr), model.OrderNr) + .SetParameter(nameof(model.PositionNr), model.PositionNr) + .SetParameter(nameof(model.SerialNr), model.SerialNr) + .SetParameter(nameof(model.Host), model.Host) + .SetParameter(nameof(model.Place), model.Place) + .ExecuteNonQuery(); private bool PalletsEntryExists(int? orderNr, int? positionNr, string serialNr) - => this.sqlClient.FirstOrDefault($@" + => this.fluentSQL + .CreateCommand($@" SELECT CAST(CASE WHEN [PalettenScan].[ID] IS NULL THEN 0 ELSE 1 END AS BIT) FROM [PalettenScan] WHERE [PalettenScan].[AuftragNr] = @{nameof(orderNr)} AND [PalettenScan].[PositionNr] = @{nameof(positionNr)} - AND [PalettenScan].[SerienNr] = @{nameof(serialNr)}", - parameters => parameters - .Add(nameof(orderNr), orderNr) - .Add(nameof(positionNr), positionNr) - .Add(nameof(serialNr), serialNr), - reader => reader.GetValue()); + AND [PalettenScan].[SerienNr] = @{nameof(serialNr)}") + .SetParameter(nameof(orderNr), orderNr) + .SetParameter(nameof(positionNr), positionNr) + .SetParameter(nameof(serialNr), serialNr) + .FirstOrDefault(x => x.GetBool()); } } \ No newline at end of file diff --git a/LaaProductionWeb/LaaProductionWeb.Services/SoftwareService.cs b/LaaProductionWeb/LaaProductionWeb.Services/SoftwareService.cs index 1022c089..60aad90a 100644 --- a/LaaProductionWeb/LaaProductionWeb.Services/SoftwareService.cs +++ b/LaaProductionWeb/LaaProductionWeb.Services/SoftwareService.cs @@ -10,9 +10,9 @@ public class SoftwareService : ISoftwareService { - private readonly ISqlClient sqlClient; + private readonly IFluentSQL sqlClient; - public SoftwareService(ISqlClient sqlClient) + public SoftwareService(IFluentSQL sqlClient) => this.sqlClient = sqlClient; public void AddFunction(short appId, string name) @@ -23,8 +23,8 @@ , [Function]) VALUES (@{nameof(appId)} , @{nameof(name)})") - .AddParameter(nameof(appId), appId) - .AddParameter(nameof(name), name) + .SetParameter(nameof(appId), appId) + .SetParameter(nameof(name), name) .ExecuteNonQuery(); public void DeleteFunction(int funcId) @@ -33,14 +33,14 @@ .CreateCommand($@" DELETE FROM [SoftwareFunctions] WHERE [Id] = @{nameof(funcId)}") - .AddParameter(nameof(funcId), funcId) + .SetParameter(nameof(funcId), funcId) .ExecuteNonQuery(); this.sqlClient .CreateCommand($@" DELETE FROM [UsersFunctions] WHERE [SoftwareFunctionId] = @{nameof(funcId)}") - .AddParameter(nameof(funcId), funcId) + .SetParameter(nameof(funcId), funcId) .ExecuteNonQuery(); } @@ -71,7 +71,7 @@ , [Function] FROM [SoftwareFunctions] WHERE [AppId] = @{nameof(appId)}") - .AddParameter(nameof(appId), appId) + .SetParameter(nameof(appId), appId) .ExecuteReader(f => new SoftwareFunction { Id = f.GetInt(), @@ -92,7 +92,7 @@ WHERE [vsa].[AppID] = @{nameof(appId)} GROUP BY [vsa].[AppID] , [vsa].[SoftwareAccess_Program]") - .AddParameter(nameof(appId), appId) + .SetParameter(nameof(appId), appId) .FirstOrDefault(x => new SoftwareOverview { AppId = x.GetSmallint(), @@ -118,7 +118,7 @@ , [SoftwareAccess_MajorVersion] DESC , [SoftwareAccess_MinorVersion] DESC , [SoftwareAccess_BuildVersion] DESC") - .AddParameter(nameof(appId), appId) + .SetParameter(nameof(appId), appId) .ExecuteReader(x => new Software { Id = x.GetInt(), @@ -174,7 +174,7 @@ ORDER BY [U].[Vorname] , [U].[Name] , [U].[Benutzername]") - .AddParameter(nameof(username), $"%{username}%") + .SetParameter(nameof(username), $"%{username}%") .ExecuteReader(x => new SoftwareUser { Id = x.GetSmallint(), @@ -215,8 +215,8 @@ ORDER BY [U].[Vorname] , [U].[Name] , [U].[Benutzername]") - .AddParameter(nameof(username), $"%{username}%") - .AddParameter(nameof(userId), userId) + .SetParameter(nameof(username), $"%{username}%") + .SetParameter(nameof(userId), userId) .ExecuteReader(x => new SoftwareUser { Id = x.GetSmallint(), @@ -234,8 +234,8 @@ UPDATE [SoftwareFunctions] SET [Function] = @{nameof(name)} WHERE [Id] = @{nameof(funcId)}") - .AddParameter(nameof(funcId), funcId) - .AddParameter(nameof(name), name) + .SetParameter(nameof(funcId), funcId) + .SetParameter(nameof(name), name) .ExecuteNonQuery(); public void UpdatePasswordHashes() @@ -262,8 +262,8 @@ UPDATE [Mitarbeiter] SET [PasswordHash] = @{nameof(password)} WHERE [MitarbeiterNr] = @{nameof(userId)}") - .AddParameter(nameof(userId), userId) - .AddParameter(nameof(password), password) + .SetParameter(nameof(userId), userId) + .SetParameter(nameof(password), password) .ExecuteNonQuery(); } } @@ -274,7 +274,7 @@ UPDATE [Mitarbeiter] SET [PasswordHash] = NULL WHERE [MitarbeiterNr] = @{nameof(userId)}") - .AddParameter(nameof(userId), userId) + .SetParameter(nameof(userId), userId) .ExecuteNonQuery(); public int ResetPassword(short userId, string password) @@ -286,8 +286,8 @@ UPDATE [Mitarbeiter] SET [PasswordHash] = @{nameof(password)} WHERE [MitarbeiterNr] = @{nameof(userId)}") - .AddParameter(nameof(userId), userId) - .AddParameter(nameof(password), password) + .SetParameter(nameof(userId), userId) + .SetParameter(nameof(password), password) .ExecuteNonQuery(); } @@ -300,7 +300,7 @@ this.sqlClient .CreateCommand($@"DELETE FROM [UsersFunctions] WHERE [UserId] = @{nameof(userId)}") - .AddParameter(nameof(userId), userId) + .SetParameter(nameof(userId), userId) .ExecuteNonQuery(); foreach (var funcId in model.Functions ?? Array.Empty()) @@ -310,8 +310,8 @@ INSERT INTO [UsersFunctions] ([UserId] ,[SoftwareFunctionId]) VALUES (@{nameof(userId)}, @{nameof(funcId)})") - .AddParameter(nameof(userId), userId) - .AddParameter(nameof(funcId), funcId) + .SetParameter(nameof(userId), userId) + .SetParameter(nameof(funcId), funcId) .ExecuteNonQuery(); } } @@ -325,7 +325,7 @@ this.sqlClient .CreateCommand($@"DELETE FROM [UsersFunctions] WHERE [SoftwareFunctionId] = @{nameof(funcId)}") - .AddParameter(nameof(funcId), funcId) + .SetParameter(nameof(funcId), funcId) .ExecuteNonQuery(); foreach (var userId in model.Users ?? Array.Empty()) @@ -335,8 +335,8 @@ INSERT INTO [UsersFunctions] ([UserId] ,[SoftwareFunctionId]) VALUES (@{nameof(userId)}, @{nameof(funcId)})") - .AddParameter(nameof(userId), userId) - .AddParameter(nameof(funcId), funcId) + .SetParameter(nameof(userId), userId) + .SetParameter(nameof(funcId), funcId) .ExecuteNonQuery(); } } diff --git a/LaaProductionWeb/LaaProductionWeb/App_Infrastructure/ServiceProvider.cs b/LaaProductionWeb/LaaProductionWeb/App_Infrastructure/ServiceProvider.cs index 8c7caca6..797db0db 100644 --- a/LaaProductionWeb/LaaProductionWeb/App_Infrastructure/ServiceProvider.cs +++ b/LaaProductionWeb/LaaProductionWeb/App_Infrastructure/ServiceProvider.cs @@ -36,7 +36,7 @@ { var services = new ServiceCollection(); - services.AddSingleton(_ => new SqlClient(Appsettings.ConnectionString)); + services.AddSingleton(_ => new FluentSQL(Appsettings.ConnectionString)); services.AddSingleton(_ => new HttpService(Appsettings.APIURL)); services.AddScoped(); diff --git a/LaaProductionWeb/LaaProductionWeb/Areas/Serach/Models/WildcardModel.cs b/LaaProductionWeb/LaaProductionWeb/Areas/Serach/Models/WildcardModel.cs index 6a8a2b45..f974843e 100644 --- a/LaaProductionWeb/LaaProductionWeb/Areas/Serach/Models/WildcardModel.cs +++ b/LaaProductionWeb/LaaProductionWeb/Areas/Serach/Models/WildcardModel.cs @@ -10,88 +10,89 @@ public class WildcardModel : IWildcardModel { - private readonly ISqlClient sqlClient; + private readonly IFluentSQL fluentSQL; - public WildcardModel(ISqlClient sqlClient) - => this.sqlClient = sqlClient; + public WildcardModel(IFluentSQL fluentSQL) + => this.fluentSQL = fluentSQL; public ModelResult> Find(ModelStateDictionary validationState, WildcardInputModel model) { if (validationState.IsValid) { var requiredFields = model.GetRequiredFields(this.Options().Value); - var ordersFound = sqlClient.ExecuteReader($@" - DECLARE @serienNr TABLE([Nr] VARCHAR(50)); - ----------------------------------------------------------------------------- - -- 1. LOOK FOR SERIAL NUMBER ------------------------------------------------ - ----------------------------------------------------------------------------- - INSERT INTO @serienNr - SELECT [APS].[SerienNr] - FROM [AuftragPositionSerienNr] AS [APS] - WHERE [APS].[SerienNr] LIKE @{nameof(model.Token)} - OR [APS].[KundeneigeneSerienNr] LIKE @{nameof(model.Token)} - OR REPLACE([APS].[KundeneigeneSerienNr], ' ', '') LIKE @{nameof(model.Token)}; - ----------------------------------------------------------------------------- - -- 2. LOOK FOR PCB NUMBER --------------------------------------------------- - ----------------------------------------------------------------------------- - INSERT INTO @serienNr - SELECT [PCBS].[MapPcbIdToSerialNumber_SerialNumber] - FROM [MapPcbIdToSerialNumber] AS [PCBS] - WHERE [PCBS].[MapPcbIdToSerialNumber_PcbId] LIKE @{nameof(model.Token)}; - ----------------------------------------------------------------------------- - -- 3. LOOK FOR FUNK ADDRESS E-REGISTER -------------------------------------- - ----------------------------------------------------------------------------- - INSERT INTO @serienNr - SELECT [ER].[Seriennummer] - FROM [eRegister] AS [ER] - WHERE [ER].[Adresse] LIKE @{nameof(model.Token)}; - ----------------------------------------------------------------------------- - -- 4. LOOK FOR FUNK ADDRESS GENESIS ----------------------------------------- - ----------------------------------------------------------------------------- - INSERT INTO @serienNr - SELECT [GM].[Seriennummer] - FROM [Genesis_Meter] AS [GM] - WHERE [GM].[Adresse] LIKE @{nameof(model.Token)}; - ----------------------------------------------------------------------------- - -- 5. TAKE ORDERS INFO ------------------------------------------------------ - ----------------------------------------------------------------------------- - SELECT DISTINCT - [KN].[KundenNr] AS [CustomerNo] - , [KN].[Name] AS [Customer] - , [AP].[FertigungsauftragNr] AS [ProductionOrderNo] - , [APS].[AuftragNr] AS [CustomerOrderNo] - , [APS].[PositionNr] AS [PosNo] - , [APS].[SerienNr] AS [SerialNo] - , [APS].[KundeneigeneSerienNr] AS [CustomerSerialNo] - , [IDN].[KurzBez] AS [KurzBez] - , [IDN].[Typ] AS [Typ] - , [IDN].[Nennweite] AS [Nennweite] - , [IDN].[Baulaenge] AS [Baulaenge] - , [AP].[Menge] AS [Quantity] - , [APS].[FabNr] AS [FabricNo] - , [IDN].[IdentNr] AS [IdentNr] - , [PCBS].[MapPcbIdToSerialNumber_PcbId] AS [PcbId] - , [ER].[Adresse] AS [ErRadioAddress] - , [GM].[Adresse] AS [GmRadioAddress] - FROM [AuftragPositionSerienNr] AS [APS] - LEFT JOIN [AuftragPosition_Gesamt] AS [AP] - ON [AP].[AuftragNr] = [APS].[AuftragNr] - AND [AP].[PositionNr] = [APS].[PositionNr] - LEFT JOIN [Auftrag_Gesamt] AS [AG] - ON [AG].[AuftragNr] = [APS].[AuftragNr] - LEFT JOIN [Kunde] AS [KN] - ON [KN].[KundenNr] = [AG].[KundenNr] - LEFT JOIN [Identnr] AS [IDN] - ON [IDN].[IdentNr] = [AP].[Identnr] - LEFT JOIN [MapPcbIdToSerialNumber] AS [PCBS] - ON [PCBS].[MapPcbIdToSerialNumber_SerialNumber] = [APS].[SerienNr] - LEFT JOIN [eRegister] AS [ER] - ON [ER].[Seriennummer] = [APS].[SerienNr] - LEFT JOIN [Genesis_Meter] AS [GM] - ON [GM].[Seriennummer] = [APS].[SerienNr] - WHERE [APS].[SerienNr] IN (SELECT [Nr] FROM @serienNr)", - parameters => parameters.Add(nameof(model.Token), model.Token), - reader => this.ToWildcardResult(reader, requiredFields)); + var ordersFound = fluentSQL + .CreateCommand($@" + DECLARE @serienNr TABLE([Nr] VARCHAR(50)); + ----------------------------------------------------------------------------- + -- 1. LOOK FOR SERIAL NUMBER ------------------------------------------------ + ----------------------------------------------------------------------------- + INSERT INTO @serienNr + SELECT [APS].[SerienNr] + FROM [AuftragPositionSerienNr] AS [APS] + WHERE [APS].[SerienNr] LIKE @{nameof(model.Token)} + OR [APS].[KundeneigeneSerienNr] LIKE @{nameof(model.Token)} + OR REPLACE([APS].[KundeneigeneSerienNr], ' ', '') LIKE @{nameof(model.Token)}; + ----------------------------------------------------------------------------- + -- 2. LOOK FOR PCB NUMBER --------------------------------------------------- + ----------------------------------------------------------------------------- + INSERT INTO @serienNr + SELECT [PCBS].[MapPcbIdToSerialNumber_SerialNumber] + FROM [MapPcbIdToSerialNumber] AS [PCBS] + WHERE [PCBS].[MapPcbIdToSerialNumber_PcbId] LIKE @{nameof(model.Token)}; + ----------------------------------------------------------------------------- + -- 3. LOOK FOR FUNK ADDRESS E-REGISTER -------------------------------------- + ----------------------------------------------------------------------------- + INSERT INTO @serienNr + SELECT [ER].[Seriennummer] + FROM [eRegister] AS [ER] + WHERE [ER].[Adresse] LIKE @{nameof(model.Token)}; + ----------------------------------------------------------------------------- + -- 4. LOOK FOR FUNK ADDRESS GENESIS ----------------------------------------- + ----------------------------------------------------------------------------- + INSERT INTO @serienNr + SELECT [GM].[Seriennummer] + FROM [Genesis_Meter] AS [GM] + WHERE [GM].[Adresse] LIKE @{nameof(model.Token)}; + ----------------------------------------------------------------------------- + -- 5. TAKE ORDERS INFO ------------------------------------------------------ + ----------------------------------------------------------------------------- + SELECT DISTINCT + [KN].[KundenNr] AS [CustomerNo] + , [KN].[Name] AS [Customer] + , [AP].[FertigungsauftragNr] AS [ProductionOrderNo] + , [APS].[AuftragNr] AS [CustomerOrderNo] + , [APS].[PositionNr] AS [PosNo] + , [APS].[SerienNr] AS [SerialNo] + , [APS].[KundeneigeneSerienNr] AS [CustomerSerialNo] + , [IDN].[KurzBez] AS [KurzBez] + , [IDN].[Typ] AS [Typ] + , [IDN].[Nennweite] AS [Nennweite] + , [IDN].[Baulaenge] AS [Baulaenge] + , [AP].[Menge] AS [Quantity] + , [APS].[FabNr] AS [FabricNo] + , [IDN].[IdentNr] AS [IdentNr] + , [PCBS].[MapPcbIdToSerialNumber_PcbId] AS [PcbId] + , [ER].[Adresse] AS [ErRadioAddress] + , [GM].[Adresse] AS [GmRadioAddress] + FROM [AuftragPositionSerienNr] AS [APS] + LEFT JOIN [AuftragPosition_Gesamt] AS [AP] + ON [AP].[AuftragNr] = [APS].[AuftragNr] + AND [AP].[PositionNr] = [APS].[PositionNr] + LEFT JOIN [Auftrag_Gesamt] AS [AG] + ON [AG].[AuftragNr] = [APS].[AuftragNr] + LEFT JOIN [Kunde] AS [KN] + ON [KN].[KundenNr] = [AG].[KundenNr] + LEFT JOIN [Identnr] AS [IDN] + ON [IDN].[IdentNr] = [AP].[Identnr] + LEFT JOIN [MapPcbIdToSerialNumber] AS [PCBS] + ON [PCBS].[MapPcbIdToSerialNumber_SerialNumber] = [APS].[SerienNr] + LEFT JOIN [eRegister] AS [ER] + ON [ER].[Seriennummer] = [APS].[SerienNr] + LEFT JOIN [Genesis_Meter] AS [GM] + ON [GM].[Seriennummer] = [APS].[SerienNr] + WHERE [APS].[SerienNr] IN (SELECT [Nr] FROM @serienNr)") + .SetParameter(nameof(model.Token), model.Token) + .ExecuteReader(reader => this.ToWildcardResult(reader, requiredFields)); if (ordersFound.Any()) { @@ -126,7 +127,7 @@ "GmRadioAddress", }; - internal WildcardResult ToWildcardResult(ISqlReader reader, IEnumerable fields) + internal WildcardResult ToWildcardResult(IFluentSQLReader reader, IEnumerable fields) { var wildcardResult = new WildcardResult(); diff --git a/LaaProductionWeb/LaaProductionWeb/Areas/Shipment/Models/ScanModel.cs b/LaaProductionWeb/LaaProductionWeb/Areas/Shipment/Models/ScanModel.cs index 33055a88..7d5f1253 100644 --- a/LaaProductionWeb/LaaProductionWeb/Areas/Shipment/Models/ScanModel.cs +++ b/LaaProductionWeb/LaaProductionWeb/Areas/Shipment/Models/ScanModel.cs @@ -10,12 +10,12 @@ public class ScanModel : IScanModel { - private readonly ISqlClient sqlClient; + private readonly IFluentSQL fluentSQL; private readonly SMTPClient smtpClient; - public ScanModel(ISqlClient sqlClient, SMTPClient smtpClient) + public ScanModel(IFluentSQL fluentSQL, SMTPClient smtpClient) { - this.sqlClient = sqlClient; + this.fluentSQL = fluentSQL; this.smtpClient = smtpClient; } @@ -23,44 +23,42 @@ { const string TEST_STATE = "25"; - var watermeterTestPassed = this.sqlClient - .FirstOrDefault( - query: $@" - SELECT [PS].[AuftragNr] - , CASE WHEN MAX([APS].[StatusFertigung]) > '{TEST_STATE}' - THEN CAST(1 AS BIT) - ELSE CAST(0 AS BIT) END - FROM [PalettenScan] AS [PS] - LEFT JOIN [AuftragPositionSerienNr] AS [APS] - ON [APS].[AuftragNr] = [PS].[AuftragNr] - AND [APS].[PositionNr] = [PS].[PositionNr] - AND (REPLACE([APS].[KundeneigeneSerienNr], ' ', '') = [PS].[SerienNr] - OR CAST([APS].[SerienNr] AS VARCHAR) = [PS].[SerienNr]) - WHERE [PS].[SerienNr] = @{nameof(serialNo)} - GROUP BY [PS].[AuftragNr]", - parameters: parameters => parameters.Add(nameof(serialNo), serialNo), - reader: reader => new KeyValuePair( - key: reader.GetString(), - value: reader.GetValue())); + var watermeterTestPassed = this.fluentSQL + .CreateCommand($@" + SELECT [PS].[AuftragNr] + , CASE WHEN MAX([APS].[StatusFertigung]) > '{TEST_STATE}' + THEN CAST(1 AS BIT) + ELSE CAST(0 AS BIT) END + FROM [PalettenScan] AS [PS] + LEFT JOIN [AuftragPositionSerienNr] AS [APS] + ON [APS].[AuftragNr] = [PS].[AuftragNr] + AND [APS].[PositionNr] = [PS].[PositionNr] + AND (REPLACE([APS].[KundeneigeneSerienNr], ' ', '') = [PS].[SerienNr] + OR CAST([APS].[SerienNr] AS VARCHAR) = [PS].[SerienNr]) + WHERE [PS].[SerienNr] = @{nameof(serialNo)} + GROUP BY [PS].[AuftragNr]") + .SetParameter(nameof(serialNo), serialNo) + .FirstOrDefault(reader => new KeyValuePair( + key: reader.GetString(), + value: reader.GetValue())); if (watermeterTestPassed.Value) { var orderNo = watermeterTestPassed.Key; - var unpackedWatermeterCount = this.sqlClient - .FirstOrDefault( - query: $@" - SELECT COUNT(1) - FROM [AuftragPositionSerienNr] AS [APS] - LEFT JOIN [PalettenScan] AS [PS] - ON [PS].[AuftragNr] = [APS].[AuftragNr] - AND [PS].[PositionNr] = [APS].[PositionNr] - AND (REPLACE([APS].[KundeneigeneSerienNr], ' ', '') = [PS].[SerienNr] - OR CAST([APS].[SerienNr] AS VARCHAR) = [PS].[SerienNr]) - WHERE [PS].[AuftragNr] = @{nameof(orderNo)} - AND [APS].[StatusFertigung] > '{TEST_STATE}' - AND [PS].[ID] IS NULL", - parameters: parameters => parameters.Add(nameof(orderNo), orderNo), - reader: reader => reader.GetValue()); + var unpackedWatermeterCount = this.fluentSQL + .CreateCommand($@" + SELECT COUNT(1) + FROM [AuftragPositionSerienNr] AS [APS] + LEFT JOIN [PalettenScan] AS [PS] + ON [PS].[AuftragNr] = [APS].[AuftragNr] + AND [PS].[PositionNr] = [APS].[PositionNr] + AND (REPLACE([APS].[KundeneigeneSerienNr], ' ', '') = [PS].[SerienNr] + OR CAST([APS].[SerienNr] AS VARCHAR) = [PS].[SerienNr]) + WHERE [PS].[AuftragNr] = @{nameof(orderNo)} + AND [APS].[StatusFertigung] > '{TEST_STATE}' + AND [PS].[ID] IS NULL") + .SetParameter(nameof(orderNo), orderNo) + .FirstOrDefault(reader => reader.GetInt()); if (unpackedWatermeterCount == 0) {