using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using System.IO; using System.Linq; using System.Text.RegularExpressions; using Janus.Configuration; using Janus.Extensions; using TechTalk.SpecFlow; namespace Janus.Database { /// /// Contains utility methods for interacting with the MxConnect database. /// public class DatabaseUtil { private static readonly Regex _sqlSplitRegex = new Regex(@"^\s*GO\s* ($ | \-\-.*$)", RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled); /// /// Executes the specified named SQL script and returns the result. /// /// The name of the SQL script to execute. /// A collection of key/value pairs representing the script parameters. /// The value returned by the specified SQL script. public static String ExecuteSqlQueryScriptWithSingleResult(String name, params KeyValuePair[] parameters) { var sql = ReadSqlScript("Scripts", name); var result = String.Empty; var testRunConfig = ScenarioContext.Current.GetTestRunConfig(); ExecuteQuery(testRunConfig.EnvironmentConnectionString, sql, parameters, (reader) => { result = reader[0].ToString(); }); return result; } /// /// Executes the specified named SQL script and returns the result as a SpecFlow object. /// /// The name of the SQL script to execute. /// A collection of key/value pairs representing the script parameters. /// The table of values returned by the specified SQL script. public static Table ExecuteSqlQueryScript(String name, params KeyValuePair[] parameters) { var sql = ReadSqlScript("Scripts", name); var result = default(Table); var testRunConfig = ScenarioContext.Current.GetTestRunConfig(); ExecuteQuery(testRunConfig.EnvironmentConnectionString, sql, parameters, (reader) => { if (result == null) { var header = Enumerable.Range(0, reader.FieldCount).Select(x => reader.GetName(x)).ToArray(); result = new Table(header); } var cells = Enumerable.Range(0, reader.FieldCount).Select(x => String.Format("{0}", reader[x])).ToArray(); result.AddRow(cells); }); return result; } /// /// Executes the specified named non-query SQL script. /// /// The name of the SQL script to execute. /// A collection of key/value pairs representing the script parameters. public static void ExecuteNonQueryScript(String name, params KeyValuePair[] parameters) { var sql = ReadSqlScript("Scripts", name); var testRunConfig = ScenarioContext.Current.GetTestRunConfig(); ExecuteNonQuery(testRunConfig.EnvironmentConnectionString, sql, parameters); } /// /// Executes the specified environment-specific SQL setup script. /// /// The current test run configuration. /// The name of the script to execute. /// A collection of key/value pairs representing the script parameters. public static void ExecuteGlobalSetupScript(TestRunConfig config, String name, params KeyValuePair[] parameters) { var sql = ReadSqlScript(Path.Combine("Setup", "global"), name); ExecuteNonQuery(config.EnvironmentConnectionString, sql, parameters); } /// /// Executes the specified globally-defined SQL setup script. /// /// The current test run configuration. /// The name of the script to execute. /// A collection of key/value pairs representing the script parameters. public static void ExecuteEnvironmentSetupScript(TestRunConfig config, String name, params KeyValuePair[] parameters) { var sql = ReadSqlScript(Path.Combine("Setup", config.Environment), name); ExecuteNonQuery(config.EnvironmentConnectionString, sql, parameters); } public static void ExecuteGlobalCleanup(TestRunConfig config) { ExecuteNonQuery(config.EnvironmentConnectionString, "DELETE FROM tbConfigurationSettingValue WHERE ConfigurationTemplateID = (SELECT ConfigurationTemplateId FROM tbConfigurationTemplate WHERE Name = 'Janus Automation')", null); } /// /// Executes the specified SQL query script. /// private static void ExecuteQuery(String connectionString, String sql, KeyValuePair[] parameters, Action action) { using (var connection = new SqlConnection(connectionString)) { connection.Open(); using (var transaction = connection.BeginTransaction()) using (var command = new SqlCommand(sql, connection, transaction)) { command.CommandTimeout = (Int32)TimeSpan.FromMinutes(15).TotalSeconds; if (parameters != null) { foreach (var parameter in parameters) command.Parameters.Add(new SqlParameter(parameter.Key, parameter.Value ?? DBNull.Value)); } using (var reader = command.ExecuteReader()) { while (!reader.IsClosed) { while (reader.Read()) { action(reader); } if (!reader.NextResult()) reader.Close(); } } transaction.Commit(); } } } /// /// Executes the specified SQL non-query script. /// private static void ExecuteNonQuery(String connectionString, String sql, KeyValuePair[] parameters) { using (var connection = new SqlConnection(connectionString)) { connection.Open(); using (var transaction = connection.BeginTransaction()) { var parts = SplitScript(sql); foreach (var part in parts) { using (var command = new SqlCommand(part, connection, transaction)) { command.CommandTimeout = (Int32)TimeSpan.FromMinutes(15).TotalSeconds; if (parameters != null) { foreach (var parameter in parameters) command.Parameters.Add(new SqlParameter(parameter.Key, (Object)parameter.Value ?? DBNull.Value)); } command.ExecuteNonQuery(); } } transaction.Commit(); } } } /// /// Reads the SQL script with the specified name. /// /// The name of the script to read. /// The script text. private static String ReadSqlScript(String directory, String name) { return File.ReadAllText(Path.Combine("Database", directory, name)); } /// /// Splits the specified script into parts separated by GO commands. /// private static IEnumerable SplitScript(String sql) { return _sqlSplitRegex.Split(sql).Where(x => !String.IsNullOrWhiteSpace(x)).Select(x => x.Trim()).ToList(); } } }