using System.Web; using Umbraco.Core.Configuration; namespace Umbraco.Core.Persistence { /// /// The default implementation for the IDatabaseFactory /// /// /// If we are running in an http context /// it will create one per context, otherwise it will be a global singleton object which is NOT thread safe /// since we need (at least) a new instance of the database object per thread. /// internal class DefaultDatabaseFactory : DisposableObject, IDatabaseFactory { private readonly string _connectionStringName; private readonly string _connectionString; private readonly string _providerName; private static volatile UmbracoDatabase _globalInstance = null; private static readonly object Locker = new object(); /// /// Default constructor initialized with the GlobalSettings.UmbracoConnectionName /// public DefaultDatabaseFactory() : this(GlobalSettings.UmbracoConnectionName) { } /// /// Constructor accepting custom connection string /// /// Name of the connection string in web.config public DefaultDatabaseFactory(string connectionStringName) { Mandate.ParameterNotNullOrEmpty(connectionStringName, "connectionStringName"); _connectionStringName = connectionStringName; } /// /// Constructor accepting custom connectino string and provider name /// /// Connection String to use with Database /// Database Provider for the Connection String public DefaultDatabaseFactory(string connectionString, string providerName) { Mandate.ParameterNotNullOrEmpty(connectionString, "connectionString"); Mandate.ParameterNotNullOrEmpty(providerName, "providerName"); _connectionString = connectionString; _providerName = providerName; } public UmbracoDatabase CreateDatabase() { //no http context, create the singleton global object if (HttpContext.Current == null) { if (_globalInstance == null) { lock (Locker) { //double check if (_globalInstance == null) { _globalInstance = string.IsNullOrEmpty(_providerName) == false && string.IsNullOrEmpty(_providerName) == false ? new UmbracoDatabase(_connectionString, _providerName) : new UmbracoDatabase(_connectionStringName); } } } return _globalInstance; } //we have an http context, so only create one per request if (!HttpContext.Current.Items.Contains(typeof(DefaultDatabaseFactory))) { HttpContext.Current.Items.Add(typeof (DefaultDatabaseFactory), string.IsNullOrEmpty(_providerName) == false && string.IsNullOrEmpty(_providerName) == false ? new UmbracoDatabase(_connectionString, _providerName) : new UmbracoDatabase(_connectionStringName)); } return (UmbracoDatabase)HttpContext.Current.Items[typeof(DefaultDatabaseFactory)]; } protected override void DisposeResources() { if (HttpContext.Current == null) { _globalInstance.Dispose(); } else { if (HttpContext.Current.Items.Contains(typeof(DefaultDatabaseFactory))) { ((UmbracoDatabase)HttpContext.Current.Items[typeof(DefaultDatabaseFactory)]).Dispose(); } } } } }