From 960ae22271d0476d38b76ef07a20de5358b27c8d Mon Sep 17 00:00:00 2001 From: sitereactor Date: Mon, 29 Oct 2012 09:49:31 -0100 Subject: [PATCH] Adding convention to column naming for table creation. Adding DatabaseContext hooked up to UmbracoContext and initialized through the CoreBootManager. Adding constant for ConnectionString name in GlobalSettings. --- .../Configuration/GlobalSettings.cs | 2 + src/Umbraco.Core/CoreBootManager.cs | 5 + src/Umbraco.Core/DatabaseContext.cs | 96 +++++++++++++++++++ .../Persistence/DatabaseFactory.cs | 12 +-- .../Migrations/Initial/BaseDataCreation.cs | 12 ++- .../Persistence/PetaPocoExtensions.cs | 6 +- .../ModelDefinitions/DefinitionFactory.cs | 11 ++- src/Umbraco.Core/Umbraco.Core.csproj | 2 +- src/Umbraco.Web/UmbracoContext.cs | 10 ++ 9 files changed, 139 insertions(+), 17 deletions(-) create mode 100644 src/Umbraco.Core/DatabaseContext.cs diff --git a/src/Umbraco.Core/Configuration/GlobalSettings.cs b/src/Umbraco.Core/Configuration/GlobalSettings.cs index 634749dd25..a044d1d210 100644 --- a/src/Umbraco.Core/Configuration/GlobalSettings.cs +++ b/src/Umbraco.Core/Configuration/GlobalSettings.cs @@ -163,6 +163,8 @@ namespace Umbraco.Core.Configuration } } + public const string UmbracoConnectionName = "umbracoDbDSN"; + /// /// Gets or sets the configuration status. This will return the version number of the currently installed umbraco instance. /// diff --git a/src/Umbraco.Core/CoreBootManager.cs b/src/Umbraco.Core/CoreBootManager.cs index d7d5b49838..8cbb3bf0b5 100644 --- a/src/Umbraco.Core/CoreBootManager.cs +++ b/src/Umbraco.Core/CoreBootManager.cs @@ -23,6 +23,7 @@ namespace Umbraco.Core private bool _isComplete = false; protected ApplicationContext ApplicationContext { get; private set; } + protected DatabaseContext DatabaseContext { get; private set; } public virtual IBootManager Initialize() { @@ -35,6 +36,10 @@ namespace Umbraco.Core //create the ApplicationContext ApplicationContext = ApplicationContext.Current = new ApplicationContext(); + //create and initialize the DatabaseContext + DatabaseContext = DatabaseContext.Current = new DatabaseContext(); + DatabaseContext.Initialize(); + InitializeResolvers(); _isInitialized = true; diff --git a/src/Umbraco.Core/DatabaseContext.cs b/src/Umbraco.Core/DatabaseContext.cs new file mode 100644 index 0000000000..27b1f02e89 --- /dev/null +++ b/src/Umbraco.Core/DatabaseContext.cs @@ -0,0 +1,96 @@ +using System; +using System.Configuration; +using System.Data.Common; +using Umbraco.Core.Configuration; +using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.SqlSyntax; + +namespace Umbraco.Core +{ + /// + /// The Umbraco Database context + /// + /// + /// One per AppDomain, represents the Umbraco database + /// + public class DatabaseContext + { + private bool _configured; + + /// + /// Constructor + /// + internal DatabaseContext() + { + } + + /// + /// Gets the current Database Context. + /// + public static DatabaseContext Current { get; internal set; } + + /// + /// Gets the object for doing CRUD operations + /// against custom tables that resides in the Umbraco database. + /// + /// + /// This should not be used for CRUD operations or queries against the + /// standard Umbraco tables! + /// + public Database Database + { + get { return DatabaseFactory.Current.Database; } + } + + /// + /// Boolean indicating whether the database has been configured + /// + public bool IsDatabaseConfigured + { + get { return _configured; } + } + + /// + /// Internal method to initialize the database configuration. + /// + /// + /// If an Umbraco connectionstring exists the database can be configured on app startup, + /// but if its a new install the entry doesn't exist and the db cannot be configured. + /// So for new installs the Initialize() method should be called after the connectionstring + /// has been added to the web.config. + /// + internal void Initialize() + { + if (ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName] != null) + { + var providerName = "System.Data.SqlClient"; + if (!string.IsNullOrEmpty(ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName].ProviderName)) + providerName = ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName].ProviderName; + + var factory = DbProviderFactories.GetFactory(providerName); + + string dbtype = (factory.GetType()).Name; + + if (dbtype.StartsWith("MySql")) + { + SyntaxConfig.SqlSyntaxProvider = MySqlSyntax.Provider; + _configured = true; + } + else if (dbtype.StartsWith("SqlCe")) + { + SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider; + _configured = true; + } + else + { + SyntaxConfig.SqlSyntaxProvider = SqlServerSyntax.Provider; + _configured = true; + } + } + else + { + _configured = false; + } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/DatabaseFactory.cs b/src/Umbraco.Core/Persistence/DatabaseFactory.cs index b6b8cb74b2..b5bf495ce5 100644 --- a/src/Umbraco.Core/Persistence/DatabaseFactory.cs +++ b/src/Umbraco.Core/Persistence/DatabaseFactory.cs @@ -1,6 +1,7 @@ using System; using System.Configuration; using System.Data.Common; +using Umbraco.Core.Configuration; namespace Umbraco.Core.Persistence { @@ -12,8 +13,7 @@ namespace Umbraco.Core.Persistence { #region Singleton - private const string ConnectionStringName = "umbracoDbDSN"; - private static readonly Database _database = new Database(ConnectionStringName); + private static readonly Database _database = new Database(GlobalSettings.UmbracoConnectionName); private static readonly Lazy lazy = new Lazy(() => new DatabaseFactory()); public static DatabaseFactory Current { get { return lazy.Value; } } @@ -40,14 +40,14 @@ namespace Umbraco.Core.Persistence get { var providerName = "System.Data.SqlClient"; - if (ConfigurationManager.ConnectionStrings[ConnectionStringName] != null) + if (ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName] != null) { - if (!string.IsNullOrEmpty(ConfigurationManager.ConnectionStrings[ConnectionStringName].ProviderName)) - providerName = ConfigurationManager.ConnectionStrings[ConnectionStringName].ProviderName; + if (!string.IsNullOrEmpty(ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName].ProviderName)) + providerName = ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName].ProviderName; } else { - throw new InvalidOperationException("Can't find a connection string with the name '" + ConnectionStringName + "'"); + throw new InvalidOperationException("Can't find a connection string with the name '" + GlobalSettings.UmbracoConnectionName + "'"); } return providerName; } diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs index 0aa0c221f1..5d0fbd4903 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs @@ -6,7 +6,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial /// /// Represents the initial data creation by running Insert for the base data. /// - public class BaseDataCreation + internal class BaseDataCreation { private readonly Database _database; @@ -233,6 +233,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 9, DataTypeId = -88, ControlId = new Guid("ec15c1e5-9d90-422a-aa52-4f7622c63bea"), DbType = "Nvarchar" }); _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 10, DataTypeId = -89, ControlId = new Guid("67db8357-ef57-493e-91ac-936d305e0f2a"), DbType = "Ntext" }); _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 11, DataTypeId = -90, ControlId = new Guid("5032a6e6-69e3-491d-bb28-cd31cd11086c"), DbType = "Nvarchar" }); + //Dropdown list //_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 12, DataTypeId = -91, ControlId = new Guid("a74ea9c9-8e18-4d2a-8cf6-73c6206c5da6"), DbType = "Nvarchar" }); _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 13, DataTypeId = -92, ControlId = new Guid("6c738306-4c17-4d88-b9bd-6546f3771597"), DbType = "Nvarchar" }); _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 14, DataTypeId = -36, ControlId = new Guid("b6fb1622-afa5-4bbf-a3cc-d9672a442222"), DbType = "Date" }); @@ -243,14 +244,23 @@ namespace Umbraco.Core.Persistence.Migrations.Initial _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 19, DataTypeId = -41, ControlId = new Guid("23e93522-3200-44e2-9f29-e61a6fcbb79a"), DbType = "Date" }); _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 20, DataTypeId = -42, ControlId = new Guid("a74ea9c9-8e18-4d2a-8cf6-73c6206c5da6"), DbType = "Integer" }); _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 21, DataTypeId = -43, ControlId = new Guid("b4471851-82b6-4c75-afa4-39fa9c6a75e9"), DbType = "Nvarchar" }); + // Fix for rich text editor backwards compatibility -> 83722133-f80c-4273-bdb6-1befaa04a612 TinyMCE DataType //_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 22, DataTypeId = -44, ControlId = new Guid("a3776494-0574-4d93-b7de-efdfdec6f2d1"), DbType = "Ntext" }); + //Radiobutton list //_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 23, DataTypeId = -128, ControlId = new Guid("a52c7c1c-c330-476e-8605-d63d3b84b6a6"), DbType = "Nvarchar" }); + //Dropdown list multiple //_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 24, DataTypeId = -129, ControlId = new Guid("928639ed-9c73-4028-920c-1e55dbb68783"), DbType = "Nvarchar" }); + //Dropdown list //_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 25, DataTypeId = -130, ControlId = new Guid("a74ea9c9-8e18-4d2a-8cf6-73c6206c5da6"), DbType = "Nvarchar" }); + //Dropdown list //_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 26, DataTypeId = -131, ControlId = new Guid("a74ea9c9-8e18-4d2a-8cf6-73c6206c5da6"), DbType = "Nvarchar" }); + //Dropdown list //_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 27, DataTypeId = -132, ControlId = new Guid("a74ea9c9-8e18-4d2a-8cf6-73c6206c5da6"), DbType = "Nvarchar" }); + //No edit //_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 28, DataTypeId = -133, ControlId = new Guid("6c738306-4c17-4d88-b9bd-6546f3771597"), DbType = "Ntext" }); + //Dropdown list multiple //_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 29, DataTypeId = -134, ControlId = new Guid("928639ed-9c73-4028-920c-1e55dbb68783"), DbType = "Nvarchar" }); + //Not found - maybe a legacy thing? //_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 30, DataTypeId = -50, ControlId = new Guid("aaf99bb2-dbbe-444d-a296-185076bf0484"), DbType = "Date" }); _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 31, DataTypeId = 1034, ControlId = new Guid("158aa029-24ed-4948-939e-c3da209e5fba"), DbType = "Integer" }); _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 32, DataTypeId = 1035, ControlId = new Guid("ead69342-f06d-4253-83ac-28000225583b"), DbType = "Integer" }); diff --git a/src/Umbraco.Core/Persistence/PetaPocoExtensions.cs b/src/Umbraco.Core/Persistence/PetaPocoExtensions.cs index b0d20f16bc..c409ddea3f 100644 --- a/src/Umbraco.Core/Persistence/PetaPocoExtensions.cs +++ b/src/Umbraco.Core/Persistence/PetaPocoExtensions.cs @@ -58,14 +58,12 @@ namespace Umbraco.Core.Persistence { int created = db.Execute(new Sql(createSql)); + //Fires the NewTable event, which is used internally to insert base data before adding constrants to the schema if (NewTable != null) { var e = new TableCreationEventArgs(); NewTable(tableName, db, e); } - - //TODO Figure out how to deal with base data before/after db and constraint creation - //Possibly add an internal task to trigger the data creation prior to creating constraints? if(!string.IsNullOrEmpty(createPrimaryKeySql)) db.Execute(new Sql(createPrimaryKeySql)); @@ -115,7 +113,7 @@ namespace Umbraco.Core.Persistence creation.InitializeDatabaseSchema(); } - static void PetaPocoExtensions_NewTable(string tableName, Database db, TableCreationEventArgs e) + private static void PetaPocoExtensions_NewTable(string tableName, Database db, TableCreationEventArgs e) { var baseDataCreation = new BaseDataCreation(db); baseDataCreation.InitializeBaseData(tableName); diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/ModelDefinitions/DefinitionFactory.cs b/src/Umbraco.Core/Persistence/SqlSyntax/ModelDefinitions/DefinitionFactory.cs index c9a5a8e4e0..959b3e7105 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/ModelDefinitions/DefinitionFactory.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/ModelDefinitions/DefinitionFactory.cs @@ -19,14 +19,15 @@ namespace Umbraco.Core.Persistence.SqlSyntax.ModelDefinitions var resultColumnAttribute = propertyInfo.FirstAttribute(); if (resultColumnAttribute != null) continue; - //Assumes ExplicitColumn attribute and thus having a ColumnAttribute with the name of the column + //Looks for ColumnAttribute with the name of the column, which would exist with ExplicitColumns + //Otherwise use the name of the property itself as the default convention var columnAttribute = propertyInfo.FirstAttribute(); - if (columnAttribute == null) continue; + string columnName = columnAttribute != null ? columnAttribute.Name : propertyInfo.Name; //Creates a column definition and adds it to the collection on the table definition var columnDefinition = new ColumnDefinition { - ColumnName = columnAttribute.Name, + ColumnName = columnName, PropertyType = propertyInfo.PropertyType }; @@ -87,7 +88,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax.ModelDefinitions var foreignKeyDefinition = new ForeignKeyDefinition { - ColumnName = columnAttribute.Name, + ColumnName = columnName, ConstraintName = foreignKeyAttribute.Name, ReferencedColumnName = referencedColumn, ReferencedTableName = referencedTable.Value @@ -105,7 +106,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax.ModelDefinitions ColumnNames = indexAttribute.ForColumns, IndexName = indexAttribute.Name, IndexType = indexAttribute.IndexType, - IndexForColumn = columnAttribute.Name + IndexForColumn = columnName }; tableDefinition.IndexDefinitions.Add(indexDefinition); } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 336453985a..e671c7064a 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -41,7 +41,6 @@ - @@ -66,6 +65,7 @@ + diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs index a56e39c43e..74cde02fe6 100644 --- a/src/Umbraco.Web/UmbracoContext.cs +++ b/src/Umbraco.Web/UmbracoContext.cs @@ -52,7 +52,9 @@ namespace Umbraco.Web Application = applicationContext; RoutesCache = routesCache; + //Consider moving these two contexts to the constructor for proper DI Services = ServiceContext.Current; + DatabaseContext = DatabaseContext.Current; // set the urls this.RequestUrl = httpContext.Request.Url; @@ -121,6 +123,14 @@ namespace Umbraco.Web /// public ServiceContext Services { get; private set; } + /// + /// Gets the current ServiceContext, which exposes the various services + /// + public DatabaseContext DatabaseContext { get; private set; } + + /// + /// Gets the + /// internal IRoutesCache RoutesCache { get; private set; } ///