From a907b5bdcd1aeae61e923a847ffac23075d56ce0 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 13 Mar 2014 20:14:56 +1100 Subject: [PATCH] Fixes up the dbconnection checker to work with all supported db types. --- .../Persistence/DbConnectionExtensions.cs | 88 +++++++++++++++++++ src/Umbraco.Core/Persistence/SqlExtensions.cs | 38 -------- src/Umbraco.Core/Umbraco.Core.csproj | 2 +- .../Install/Controllers/InstallController.cs | 5 +- src/Umbraco.Web/Install/DatabaseHelper.cs | 7 +- .../InstallSteps/DatabaseConfigureStep.cs | 35 +------- .../Install/InstallSteps/NewInstallStep.cs | 8 +- 7 files changed, 106 insertions(+), 77 deletions(-) create mode 100644 src/Umbraco.Core/Persistence/DbConnectionExtensions.cs delete mode 100644 src/Umbraco.Core/Persistence/SqlExtensions.cs diff --git a/src/Umbraco.Core/Persistence/DbConnectionExtensions.cs b/src/Umbraco.Core/Persistence/DbConnectionExtensions.cs new file mode 100644 index 0000000000..f7bd9e31c1 --- /dev/null +++ b/src/Umbraco.Core/Persistence/DbConnectionExtensions.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Data.Common; +using System.Data.SqlClient; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Umbraco.Core.Persistence +{ + internal static class DbConnectionExtensions + { + + public static DatabaseProviders DetectProviderFromConnectionString(string connString) + { + var builder = new DbConnectionStringBuilder {ConnectionString = connString}; + var allKeys = builder.Keys.Cast(); + + var mySql = new[] {"Server", "Database", "Uid", "Pwd"}; + if (mySql.All(x => allKeys.InvariantContains(x))) + { + return DatabaseProviders.MySql; + } + + if (allKeys.InvariantContains("Data Source") + //this dictionary is case insensitive + && builder["Data source"].ToString().InvariantContains(".sdf")) + { + return DatabaseProviders.SqlServerCE; + } + + return DatabaseProviders.SqlServer; + } + + public static bool IsConnectionAvailable(string connString, DatabaseProviders provider) + { + DbProviderFactory factory; + switch (provider) + { + case DatabaseProviders.SqlServer: + case DatabaseProviders.SqlAzure: + factory = DbProviderFactories.GetFactory("System.Data.SqlClient"); + break; + case DatabaseProviders.SqlServerCE: + factory = DbProviderFactories.GetFactory("System.Data.SqlServerCe.4.0"); + break; + case DatabaseProviders.MySql: + factory = DbProviderFactories.GetFactory("MySql.Data.MySqlClient"); + break; + case DatabaseProviders.PostgreSQL: + case DatabaseProviders.Oracle: + case DatabaseProviders.SQLite: + default: + throw new NotSupportedException("The provider " + provider + " is not supported"); + } + + var conn = factory.CreateConnection(); + if (conn == null) + { + throw new InvalidOperationException("Could not create a connection for provider " + provider); + } + conn.ConnectionString = connString; + using (var connection = conn) + { + return connection.IsAvailable(); + } + } + + public static bool IsAvailable(this IDbConnection connection) + { + try + { + connection.Open(); + connection.Close(); + } + catch (SqlException) + { + return false; + } + + return true; + } + + + } +} diff --git a/src/Umbraco.Core/Persistence/SqlExtensions.cs b/src/Umbraco.Core/Persistence/SqlExtensions.cs deleted file mode 100644 index 7fbd254709..0000000000 --- a/src/Umbraco.Core/Persistence/SqlExtensions.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Data.SqlClient; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Umbraco.Core.Persistence -{ - //TODO: check if any of this works and for what databse types it works for: - // ref: http://stackoverflow.com/questions/16171144/how-to-check-for-database-availability - - internal static class SqlExtensions - { - public static bool IsConnectionAvailable(string connString) - { - using (var connection = new SqlConnection(connString)) - { - return connection.IsAvailable(); - } - } - - public static bool IsAvailable(this SqlConnection connection) - { - try - { - connection.Open(); - connection.Close(); - } - catch (SqlException) - { - return false; - } - - return true; - } - } -} diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index d545f65e13..c3e82a2120 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -358,7 +358,7 @@ - + diff --git a/src/Umbraco.Web/Install/Controllers/InstallController.cs b/src/Umbraco.Web/Install/Controllers/InstallController.cs index 97c8246e71..9f60a7b748 100644 --- a/src/Umbraco.Web/Install/Controllers/InstallController.cs +++ b/src/Umbraco.Web/Install/Controllers/InstallController.cs @@ -38,8 +38,9 @@ namespace Umbraco.Web.Install.Controllers public ActionResult Index() { //if this is not an upgrade we will log in with the default user. - // It's not considered an upgrade if the ConfigurationStatus is missing or empty. - if (string.IsNullOrWhiteSpace(GlobalSettings.ConfigurationStatus) == false) + // It's not considered an upgrade if the ConfigurationStatus is missing or empty or if the db is not configured. + if (string.IsNullOrWhiteSpace(GlobalSettings.ConfigurationStatus) == false + && ApplicationContext.Current.DatabaseContext.IsDatabaseConfigured) { Version current; if (Version.TryParse(GlobalSettings.ConfigurationStatus, out current)) diff --git a/src/Umbraco.Web/Install/DatabaseHelper.cs b/src/Umbraco.Web/Install/DatabaseHelper.cs index 092ca61e62..cb2263628b 100644 --- a/src/Umbraco.Web/Install/DatabaseHelper.cs +++ b/src/Umbraco.Web/Install/DatabaseHelper.cs @@ -14,11 +14,13 @@ namespace Umbraco.Web.Install internal bool CheckConnection(DatabaseModel database, ApplicationContext applicationContext) { string connectionString; + DatabaseProviders provider; var dbContext = applicationContext.DatabaseContext; if (database.ConnectionString.IsNullOrWhiteSpace() == false) { connectionString = database.ConnectionString; + provider = DbConnectionExtensions.DetectProviderFromConnectionString(connectionString); } else if (database.DatabaseType == DatabaseType.SqlCe) { @@ -30,6 +32,7 @@ namespace Umbraco.Web.Install { connectionString = dbContext.GetIntegratedSecurityDatabaseConnectionString( database.Server, database.DatabaseName); + provider = DatabaseProviders.SqlServer;; } else { @@ -38,9 +41,11 @@ namespace Umbraco.Web.Install database.Server, database.DatabaseName, database.Login, database.Password, database.DatabaseType.ToString(), out providerName); + + provider = database.DatabaseType == DatabaseType.MySql ? DatabaseProviders.MySql : DatabaseProviders.SqlServer; } - return SqlExtensions.IsConnectionAvailable(connectionString); + return DbConnectionExtensions.IsConnectionAvailable(connectionString, provider); } } } diff --git a/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs b/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs index 5989194775..982d9b76ab 100644 --- a/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs @@ -33,7 +33,9 @@ namespace Umbraco.Web.Install.InstallSteps database = new DatabaseModel(); } - if (CheckConnection(database) == false) + var dbHelper = new DatabaseHelper(); + + if (dbHelper.CheckConnection(database, _applicationContext) == false) { throw new InvalidOperationException("Could not connect to the database"); } @@ -41,37 +43,6 @@ namespace Umbraco.Web.Install.InstallSteps return null; } - private bool CheckConnection(DatabaseModel database) - { - string connectionString; - var dbContext = _applicationContext.DatabaseContext; - if (database.ConnectionString.IsNullOrWhiteSpace() == false) - { - connectionString = database.ConnectionString; - } - else if (database.DatabaseType == DatabaseType.SqlCe) - { - //we do not test this connection - return true; - //connectionString = dbContext.GetEmbeddedDatabaseConnectionString(); - } - else if (database.IntegratedAuth) - { - connectionString = dbContext.GetIntegratedSecurityDatabaseConnectionString( - database.Server, database.DatabaseName); - } - else - { - string providerName; - connectionString = dbContext.GetDatabaseConnectionString( - database.Server, database.DatabaseName, database.Login, database.Password, - database.DatabaseType.ToString(), - out providerName); - } - - return SqlExtensions.IsConnectionAvailable(connectionString); - } - private void ConfigureConnection(DatabaseModel database) { var dbContext = _applicationContext.DatabaseContext; diff --git a/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs b/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs index d2d764d5eb..f41ca62d99 100644 --- a/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs @@ -4,6 +4,7 @@ using System.Configuration; using System.Web.Security; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Persistence; using Umbraco.Web.Install.Models; namespace Umbraco.Web.Install.InstallSteps @@ -102,12 +103,13 @@ namespace Umbraco.Web.Install.InstallSteps public override bool RequiresExecution(UserModel model) { - //if there's already a version then there should def be a user - if (GlobalSettings.ConfigurationStatus.IsNullOrWhiteSpace() == false) return false; - //now we have to check if this is really a new install, the db might be configured and might contain data var databaseSettings = ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName]; + //if there's already a version then there should def be a user but in some cases someone may have + // left a version number in there but cleared out their db conn string, in that case, it's really a new install. + if (GlobalSettings.ConfigurationStatus.IsNullOrWhiteSpace() == false && databaseSettings != null) return false; + if (_applicationContext.DatabaseContext.IsConnectionStringConfigured(databaseSettings) && _applicationContext.DatabaseContext.IsDatabaseConfigured) {