using DbAPI.Connections; using DbAPI.Errors; using DbAPI.Logging; using DTS.Common.Classes; using DTS.Common.Interface.Database; using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using System.Diagnostics; using System.Linq; namespace DbAPI.Database { /// /// no real reason to export this, this class handles the implementation for the interface /// /// internal class Database : IDatabase { public ulong GetDatabaseVersion(IUserDbRecord user, IConnectionDetails connection, out int version) { version = 0; //allow querying database version without a user var ret = ConnectionManager.GetSqlCommand(connection, out var cmd, "sp_DBVersionGet"); if (ret != ErrorCodes.ERROR_SUCCESS) { return ret; } try { cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.Add(new SqlParameter("@Version", SqlDbType.Int) { Value = DBNull.Value }); var reader = cmd.ExecuteReader(); var dbVersionsList = new List(); while (reader.Read()) { var tmp = Utility.GetInt(reader, "Version"); dbVersionsList.Add(tmp); } reader.Close(); version = dbVersionsList.Max(); return ErrorCodes.ERROR_SUCCESS; } catch (Exception ex) { LogManager.Log(TraceEventType.Error, LogManager.LogEvents.Information, ex.Message); version = 0; return ErrorCodes.ERROR_UNKNOWN; } finally { cmd.Connection.Dispose(); } } public int GetSQLVersion(IConnectionDetails connection) { var sqlVersion = 0; var ret = ConnectionManager.GetSqlCommand(connection, out var cmd); if (ret == ErrorCodes.ERROR_SUCCESS) { try { var serverVersion = cmd.Connection.ServerVersion; string[] serverVersionDetails = serverVersion.Split(new string[] { "." }, StringSplitOptions.None); sqlVersion = int.Parse(serverVersionDetails[0]); } catch (Exception ex) { LogManager.Log(TraceEventType.Error, LogManager.LogEvents.Information, ex.Message); sqlVersion = 0; } finally { cmd.Connection.Dispose(); } } return sqlVersion; } public ulong InsertDatabaseVersion(IUserDbRecord user, IConnectionDetails connection, int version, int step, DateTime date, string remarks, string userField) { if (!DbAPI.Connections.IsUserLoggedIn(user, connection)) { return ErrorCodes.ERROR_ACCESS_DENIED; } var ret = ConnectionManager.GetSqlCommand(connection, out var cmd, "sp_DbVersionInsert"); if (ret != ErrorCodes.ERROR_SUCCESS) { return ret; } try { cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.Add(new SqlParameter("@Version", SqlDbType.Int) { Value = version }); cmd.Parameters.Add(new SqlParameter("@Step", SqlDbType.Int) { Value = step }); cmd.Parameters.Add(new SqlParameter("@Date", SqlDbType.DateTime) { Value = date }); cmd.Parameters.Add(new SqlParameter("@Remarks", SqlDbType.NVarChar, 255) { Value = remarks }); cmd.Parameters.Add(new SqlParameter("@UserField", SqlDbType.NVarChar, 255) { Value = userField }); var newId = new SqlParameter("@new_id", SqlDbType.Int) { Direction = ParameterDirection.Output }; cmd.Parameters.Add(newId); var errorNumber = new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output }; cmd.Parameters.Add(errorNumber); var errorMessage = new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250) { Direction = ParameterDirection.Output }; cmd.Parameters.Add(errorMessage); var reader = cmd.ExecuteReader(); if (!DBNull.Value.Equals(errorNumber.Value)) { var error = Convert.ToInt32(errorNumber.Value); if (0 != error) { return ErrorCodes.ERROR_UNKNOWN; } } return ErrorCodes.ERROR_SUCCESS; } catch (Exception ex) { LogManager.Log(TraceEventType.Error, LogManager.LogEvents.Information, ex.Message); return ErrorCodes.ERROR_UNKNOWN; } finally { cmd.Connection.Dispose(); } } /// /// returns the command text to use for a given stored procedure that might be versioned /// /// connection stored procedure is to be run on /// the stored procedure name /// the code/requested version of the stored procedure /// the stored procedure name that should be called given the current db and client versions public static string GetStoredProcedureVersion(IConnectionDetails connection, string storedProcedure, int clientDbVersion) { var ret = DbAPI.GetStoredProcedureToUse(connection, storedProcedure, clientDbVersion, out var storedProcedureVersionToUse); if (ret != ErrorCodes.ERROR_SUCCESS) { return storedProcedure; } return storedProcedureVersionToUse == 0 ? storedProcedure : $"{storedProcedure}_{storedProcedureVersionToUse}"; } /// /// returns the command text to use for a given stored procedure that might be versioned /// retrieves/stores it in a cache to reduce calls to db ... /// /// connection stored procedure is to be run on /// the stored procedure name /// the code/requested version of the stored procedure /// the stored procedure name that should be called given the current db and client versions public static string GetStoredProcedureVersionCached(IConnectionDetails connection, string storedProcedure) { var ret = DbAPI.GetStoredProcedureToUseCached(connection, storedProcedure, connection.ClientDbVersion, out var storedProcedureVersionToUse); if (ret != ErrorCodes.ERROR_SUCCESS) { return storedProcedure; } return storedProcedureVersionToUse == 0 ? storedProcedure : $"{storedProcedure}_{storedProcedureVersionToUse}"; } /// /// Prepares a Sql command based on client version /// /// /// /// /// /// /// /// public static ulong PrepareForDbAccess(IUserDbRecord user, IConnectionDetails connection, int clientDbVersion, string storedProcedure, out int storedProcedureVersionToUse, out SqlCommand cmd) { storedProcedureVersionToUse = 0; cmd = null; if (!DbAPI.Connections.IsUserLoggedIn(user, connection)) { return ErrorCodes.ERROR_ACCESS_DENIED; } var ret = DbAPI.GetStoredProcedureToUse(connection, storedProcedure, clientDbVersion, out storedProcedureVersionToUse); if (ret != ErrorCodes.ERROR_SUCCESS) { return ret; } ret = ConnectionManager.GetSqlCommand(connection, out cmd, storedProcedureVersionToUse == 0 ? storedProcedure : $"{storedProcedure}_{storedProcedureVersionToUse}"); if (ret != ErrorCodes.ERROR_SUCCESS) { return ret; } return ret; } } }