Refactoring database creation, adding sql syntax provider to account for differences in syntax between sql, ce and mysql.

Adding MySql unit test.
This commit is contained in:
sitereactor
2012-10-19 13:20:57 -02:00
parent e34298c9f3
commit c1909eccf5
47 changed files with 844 additions and 384 deletions

View File

@@ -10,7 +10,7 @@ namespace Umbraco.Core.Models.Rdbms
{
[Column("appAlias")]
[PrimaryKeyColumn(AutoIncrement = false, Clustered = true)]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 50)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 50)]
public string AppAlias { get; set; }
[Column("appIcon")]

View File

@@ -32,7 +32,7 @@ namespace Umbraco.Core.Models.Rdbms
[Column("description")]
[NullSetting(NullSetting = NullSettings.Null)]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 1500)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 1500)]
public string Description { get; set; }
[Column("isContainer")]

View File

@@ -22,7 +22,7 @@ namespace Umbraco.Core.Models.Rdbms
public Guid ControlId { get; set; }
[Column("dbType")]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 50)]//NOTE Is set to [varchar] (50) in Sql Server script
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 50)]//NOTE Is set to [varchar] (50) in Sql Server script
public string DbType { get; set; }
[ResultColumn]

View File

@@ -18,7 +18,7 @@ namespace Umbraco.Core.Models.Rdbms
[Column("value")]
[NullSetting(NullSetting = NullSettings.Null)]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 2500)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 2500)]
public string Value { get; set; }
[Column("sortorder")]
@@ -26,7 +26,7 @@ namespace Umbraco.Core.Models.Rdbms
[Column("alias")]
[NullSetting(NullSetting = NullSettings.Null)]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 50)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 50)]
public string Alias { get; set; }
}
}

View File

@@ -22,7 +22,7 @@ namespace Umbraco.Core.Models.Rdbms
public Guid Parent { get; set; }
[Column("key")]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 1000)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 1000)]
public string Key { get; set; }
[ResultColumn]

View File

@@ -26,7 +26,7 @@ namespace Umbraco.Core.Models.Rdbms
public Guid VersionId { get; set; }
[Column("text")]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 255)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 255)]
public string Text { get; set; }
[Column("releaseDate")]
@@ -48,7 +48,7 @@ namespace Umbraco.Core.Models.Rdbms
[Column("alias")]
[NullSetting(NullSetting = NullSettings.Null)]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 255)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 255)]
public string Alias { get; set; }
[Column("newest")]

View File

@@ -15,12 +15,12 @@ namespace Umbraco.Core.Models.Rdbms
[Column("languageISOCode")]
[Index(IndexTypes.UniqueNonClustered)]
[NullSetting(NullSetting = NullSettings.Null)]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 10)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 10)]
public string IsoCode { get; set; }
[Column("languageCultureName")]
[NullSetting(NullSetting = NullSettings.Null)]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 100)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 100)]
public string CultureName { get; set; }
}
}

View File

@@ -21,7 +21,7 @@ namespace Umbraco.Core.Models.Rdbms
public Guid UniqueId { get; set; }
[Column("value")]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 1000)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 1000)]
public string Value { get; set; }
}
}

View File

@@ -25,12 +25,12 @@ namespace Umbraco.Core.Models.Rdbms
public DateTime Datestamp { get; set; }
[Column("logHeader")]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 50)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 50)]
public string Header { get; set; }
[Column("logComment")]
[NullSetting(NullSetting = NullSettings.Null)]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 4000)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 4000)]
public string Comment { get; set; }
}
}

View File

@@ -29,7 +29,7 @@ namespace Umbraco.Core.Models.Rdbms
public byte SortOrder { get; set; }
[Column("macroPropertyAlias")]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 50)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 50)]
public string Alias { get; set; }
[Column("macroPropertyName")]

View File

@@ -13,7 +13,7 @@ namespace Umbraco.Core.Models.Rdbms
public short Id { get; set; }
[Column("macroPropertyTypeAlias")]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 50)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 50)]
[NullSetting(NullSetting = NullSettings.Null)]
public string Alias { get; set; }

View File

@@ -15,17 +15,17 @@ namespace Umbraco.Core.Models.Rdbms
public int NodeId { get; set; }
[Column("Email")]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 1000)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 1000)]
[Constraint(Default = "''")]
public string Email { get; set; }
[Column("LoginName")]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 1000)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 1000)]
[Constraint(Default = "''")]
public string LoginName { get; set; }
[Column("Password")]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 1000)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 1000)]
[Constraint(Default = "''")]
public string Password { get; set; }
}

View File

@@ -11,55 +11,55 @@ namespace Umbraco.Core.Models.Rdbms
{
[Column("id")]
[PrimaryKeyColumn(Name = "PK_structure")]
[DatabaseType(DatabaseTypes.Integer)]
//[DatabaseType(DatabaseTypes.Integer)]
public int NodeId { get; set; }
[Column("trashed")]
[DatabaseType(DatabaseTypes.Bool)]
//[DatabaseType(DatabaseTypes.Bool)]
[Constraint(Default = "0")]
public bool Trashed { get; set; }
[Column("parentID")]
[DatabaseType(DatabaseTypes.Integer)]
//[DatabaseType(DatabaseTypes.Integer)]
[ForeignKey(typeof(NodeDto))]
[IndexAttribute(IndexTypes.NonClustered, Name = "IX_umbracoNodeParentId")]
public int ParentId { get; set; }
[Column("nodeUser")]
[DatabaseType(DatabaseTypes.Integer)]
//[DatabaseType(DatabaseTypes.Integer)]
[NullSetting(NullSetting = NullSettings.Null)]
public int? UserId { get; set; }
[Column("level")]
[DatabaseType(DatabaseTypes.SmallInteger)]
//[DatabaseType(DatabaseTypes.SmallInteger)]
public short Level { get; set; }
[Column("path")]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 150)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 150)]
public string Path { get; set; }
[Column("sortOrder")]
[DatabaseType(DatabaseTypes.Integer)]
//[DatabaseType(DatabaseTypes.Integer)]
public int SortOrder { get; set; }
[Column("uniqueID")]
[DatabaseType(DatabaseTypes.UniqueIdentifier)]
//[DatabaseType(DatabaseTypes.UniqueIdentifier)]
[NullSetting(NullSetting = NullSettings.Null)]
public Guid? UniqueId { get; set; }
[Column("text")]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 255)]
//[DatabaseType(DatabaseTypes.Nvarchar, Length = 255)]
[NullSetting(NullSetting = NullSettings.Null)]
public string Text { get; set; }
[Column("nodeObjectType")]
[DatabaseType(DatabaseTypes.UniqueIdentifier)]
//[DatabaseType(DatabaseTypes.UniqueIdentifier)]
[NullSetting(NullSetting = NullSettings.Null)]
[IndexAttribute(IndexTypes.NonClustered, Name = "IX_umbracoNodeObjectType")]
public Guid? NodeObjectType { get; set; }
[Column("createDate")]
[DatabaseType(DatabaseTypes.DateTime)]
//[DatabaseType(DatabaseTypes.DateTime)]
[Constraint(Default = "getdate()")]
public DateTime CreateDate { get; set; }
}

View File

@@ -22,7 +22,7 @@ namespace Umbraco.Core.Models.Rdbms
public DateTime Timestamp { get; set; }
[Column("xml")]
[DatabaseType(DatabaseTypes.Ntext)]
[DatabaseType(DatabaseTypes.NTEXT)]
public string Xml { get; set; }
}
}

View File

@@ -39,12 +39,12 @@ namespace Umbraco.Core.Models.Rdbms
[Column("dataNvarchar")]
[NullSetting(NullSetting = NullSettings.Null)]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 500)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 500)]
public string VarChar { get; set; }
[Column("dataNtext")]
[NullSetting(NullSetting = NullSettings.Null)]
[DatabaseType(DatabaseTypes.Ntext)]
[DatabaseType(DatabaseTypes.NTEXT)]
public string Text { get; set; }
[ResultColumn]

View File

@@ -34,7 +34,7 @@ namespace Umbraco.Core.Models.Rdbms
[Column("helpText")]
[NullSetting(NullSetting = NullSettings.Null)]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 1000)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 1000)]
public string HelpText { get; set; }
[Column("sortOrder")]
@@ -51,7 +51,7 @@ namespace Umbraco.Core.Models.Rdbms
[Column("Description")]
[NullSetting(NullSetting = NullSettings.Null)]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 2000)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 2000)]
public string Description { get; set; }
[ResultColumn]

View File

@@ -30,7 +30,7 @@ namespace Umbraco.Core.Models.Rdbms
public DateTime Datetime { get; set; }
[Column("comment")]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 1000)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 1000)]
public string Comment { get; set; }
}
}

View File

@@ -27,7 +27,7 @@ namespace Umbraco.Core.Models.Rdbms
[Column("alias")]
[NullSetting(NullSetting = NullSettings.Null)]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 100)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 100)]
public string Alias { get; set; }
}
}

View File

@@ -14,11 +14,11 @@ namespace Umbraco.Core.Models.Rdbms
public int NodeId { get; set; }
[Column("filename")]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 100)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 100)]
public string Filename { get; set; }
[Column("content")]
[DatabaseType(DatabaseTypes.Ntext)]
[DatabaseType(DatabaseTypes.NTEXT)]
[NullSetting(NullSetting = NullSettings.Null)]
public string Content { get; set; }
}

View File

@@ -18,12 +18,12 @@ namespace Umbraco.Core.Models.Rdbms
[Column("stylesheetPropertyAlias")]
[NullSetting(NullSetting = NullSettings.Null)]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 50)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 50)]
public string Alias { get; set; }
[Column("stylesheetPropertyValue")]
[NullSetting(NullSetting = NullSettings.Null)]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 400)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 400)]
public string Value { get; set; }
}
}

View File

@@ -14,7 +14,7 @@ namespace Umbraco.Core.Models.Rdbms
[Column("tag")]
[NullSetting(NullSetting = NullSettings.Null)]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 200)]//NOTE Is set to [varchar] (200) in Sql Server script
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 200)]//NOTE Is set to [varchar] (200) in Sql Server script
public string Tag { get; set; }
[Column("ParentId")]
@@ -23,7 +23,7 @@ namespace Umbraco.Core.Models.Rdbms
[Column("group")]
[NullSetting(NullSetting = NullSettings.Null)]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 100)]//NOTE Is set to [varchar] (100) in Sql Server script
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 100)]//NOTE Is set to [varchar] (100) in Sql Server script
public string Group { get; set; }
}
}

View File

@@ -39,7 +39,7 @@ namespace Umbraco.Core.Models.Rdbms
[Column("Comment")]
[NullSetting(NullSetting = NullSettings.Null)]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 500)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 500)]
public string Comment { get; set; }
}
}

View File

@@ -23,12 +23,12 @@ namespace Umbraco.Core.Models.Rdbms
public int? Master { get; set; }
[Column("alias")]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 100)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 100)]
[NullSetting(NullSetting = NullSettings.Null)]
public string Alias { get; set; }
[Column("design")]
[DatabaseType(DatabaseTypes.Ntext)]
[DatabaseType(DatabaseTypes.NTEXT)]
public string Design { get; set; }
}
}

View File

@@ -14,7 +14,7 @@ namespace Umbraco.Core.Models.Rdbms
public int UserId { get; set; }
[Column("app")]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 50)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 50)]
public string AppAlias { get; set; }
}
}

View File

@@ -18,7 +18,7 @@ namespace Umbraco.Core.Models.Rdbms
public int NodeId { get; set; }
[Column("action")]
[DatabaseType(DatabaseTypes.Nchar, Length = 1)]
[DatabaseType(DatabaseTypes.NCHAR, Length = 1)]
public string Action { get; set; }
}
}

View File

@@ -35,12 +35,12 @@ namespace Umbraco.Core.Models.Rdbms
public string UserName { get; set; }
[Column("userLogin")]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 125)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 125)]
[Index(IndexTypes.NonClustered)]
public string Login { get; set; }
[Column("userPassword")]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 125)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 125)]
public string Password { get; set; }
[Column("userEmail")]
@@ -48,12 +48,12 @@ namespace Umbraco.Core.Models.Rdbms
[Column("userDefaultPermissions")]
[NullSetting(NullSetting = NullSettings.Null)]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 50)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 50)]
public string DefaultPermissions { get; set; }
[Column("userLanguage")]
[NullSetting(NullSetting = NullSettings.Null)]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 10)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 10)]
public string UserLanguage { get; set; }
[Column("defaultToLiveEditing")]

View File

@@ -13,7 +13,7 @@ namespace Umbraco.Core.Models.Rdbms
public short Id { get; set; }
[Column("userTypeAlias")]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 50)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 50)]
[NullSetting(NullSetting = NullSettings.Null)]
public string Alias { get; set; }
@@ -21,7 +21,7 @@ namespace Umbraco.Core.Models.Rdbms
public string Name { get; set; }
[Column("userTypeDefaultPermissions")]
[DatabaseType(DatabaseTypes.Nvarchar, Length = 50)]
[DatabaseType(DatabaseTypes.NVARCHAR, Length = 50)]
[NullSetting(NullSetting = NullSettings.Null)]
public string DefaultPermissions { get; set; }
}

View File

@@ -1,148 +0,0 @@
namespace Umbraco.Core.Persistence.DatabaseAnnotations
{
internal static class AttributeExtensions
{
public static string ToSqlSyntax(this NullSettings settings)
{
return settings == NullSettings.Null ? "NULL" : "NOT NULL";
}
public static string ToSqlSyntax(this NullSettingAttribute attribute)
{
return attribute.NullSetting.ToSqlSyntax();
}
public static string ToSqlSyntax(this DatabaseTypes databaseTypes, int length)
{
string syntax = string.Empty;
switch (databaseTypes)
{
case DatabaseTypes.Bool:
syntax = "[bit]";
break;
case DatabaseTypes.Ntext:
syntax = "[ntext]";
break;
case DatabaseTypes.DateTime:
syntax = "[datetime]";
break;
case DatabaseTypes.UniqueIdentifier:
syntax = "[uniqueidentifier]";
break;
case DatabaseTypes.SmallInteger:
syntax = "[smallint]";
break;
case DatabaseTypes.TinyInteger:
syntax = "[tinyint]";
break;
case DatabaseTypes.Integer:
syntax = "[int]";
break;
case DatabaseTypes.Nchar:
syntax = "[nchar]";
if (length > 0)
syntax += string.Format(" ({0})", length);
break;
case DatabaseTypes.Nvarchar:
syntax = "[nvarchar]";
if (length > 0)
syntax += string.Format(" ({0})", length);
break;
}
return syntax;
}
public static string ToSqlSyntax(this DatabaseTypeAttribute attribute)
{
return attribute.DatabaseType.ToSqlSyntax(attribute.Length);
}
public static string ToSqlSyntax(this PrimaryKeyColumnAttribute attribute)
{
string syntax = string.Empty;
if (attribute.AutoIncrement)
syntax = " IDENTITY(1, 1)";
return syntax;
}
public static string ToSqlSyntax(this PrimaryKeyColumnAttribute attribute, string tableName, string propertyName)
{
string constraintName = string.IsNullOrEmpty(attribute.Name) ? string.Format("PK_{0}", tableName) : attribute.Name;
string clustered = attribute.Clustered ? "CLUSTERED" : "NONCLUSTERED";
if (DatabaseFactory.Current.DatabaseProvider == DatabaseProviders.SqlServerCE)
clustered = string.Empty;
string syntax = string.IsNullOrEmpty(attribute.OnColumns)
? string.Format("ALTER TABLE [{0}] ADD CONSTRAINT [{1}] PRIMARY KEY {2} ([{3}])",
tableName, constraintName, clustered, propertyName)
: string.Format("ALTER TABLE [{0}] ADD CONSTRAINT [{1}] PRIMARY KEY {2} ({3})",
tableName, constraintName, clustered, attribute.OnColumns);
return syntax;
}
public static string ToSqlSyntax(this ConstraintAttribute attribute, string tableName, string propertyName)
{
if (!string.IsNullOrEmpty(attribute.Name))
return string.Format("CONSTRAINT [{0}] DEFAULT ({1})", attribute.Name, attribute.Default);
return string.Format("CONSTRAINT [DF_{0}_{1}] DEFAULT ({2})", tableName, propertyName, attribute.Default);
}
public static string ToSqlSyntax(this ForeignKeyAttribute attribute, string tableName, string propertyName)
{
var tableNameAttribute = attribute.Type.FirstAttribute<TableNameAttribute>();
var primaryKeyAttribute = attribute.Type.FirstAttribute<PrimaryKeyAttribute>();
var referencedTableName = tableNameAttribute.Value;
string constraintName = string.IsNullOrEmpty(attribute.Name)
? string.Format("FK_{0}_{1}", tableName, referencedTableName)
: attribute.Name;
string referencedColumn = string.IsNullOrEmpty(attribute.Column)
? primaryKeyAttribute.Value
: attribute.Column;
string syntax =
string.Format(
"ALTER TABLE [{0}] ADD CONSTRAINT [{1}] FOREIGN KEY ([{2}]) REFERENCES [{3}] ([{4}])",
tableName, constraintName, propertyName, referencedTableName, referencedColumn);
return syntax;
}
public static string ToSqlSyntax(this IndexAttribute attribute, string tableName, string propertyName)
{
string indexType = string.Empty;
switch (attribute.IndexType)
{
case IndexTypes.Clustered:
indexType = "CLUSTERED";
break;
case IndexTypes.NonClustered:
indexType = "NONCLUSTERED";
break;
case IndexTypes.PrimaryXml:
indexType = "PRIMARYXML";
break;
case IndexTypes.Spartial:
indexType = "SPARTIAL";
break;
case IndexTypes.UniqueNonClustered:
indexType = "UNIQUE NONCLUSTERED";
break;
}
string name = string.IsNullOrEmpty(attribute.Name) ? string.Format("IX_{0}_{1}", tableName, propertyName) : attribute.Name;
string syntax = string.IsNullOrEmpty(attribute.ForColumns)
? string.Format("CREATE {0} INDEX [{1}] ON [{2}] ([{3}])", indexType, name, tableName,
propertyName)
: string.Format("CREATE {0} INDEX [{1}] ON [{2}] ({3})", indexType, name, tableName,
attribute.ForColumns);
return syntax;
}
}
}

View File

@@ -2,14 +2,14 @@
{
public enum DatabaseTypes
{
Integer,
SmallInteger,
TinyInteger,
UniqueIdentifier,
DateTime,
Ntext,
Nvarchar,
Bool,
Nchar
INTEGER,
SMALLINTEGER,
TINYINTEGER,
UNIQUEIDENTIFIER,
DATETIME,
NTEXT,
NVARCHAR,
BOOL,
NCHAR
}
}

View File

@@ -4,8 +4,6 @@
{
Clustered,
NonClustered,
UniqueNonClustered,
PrimaryXml,
Spartial
UniqueNonClustered
}
}

View File

@@ -1,9 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.Migrations.Initial;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Persistence.SqlSyntax.ModelDefinitions;
namespace Umbraco.Core.Persistence
{
@@ -25,179 +23,49 @@ namespace Umbraco.Core.Persistence
public static void CreateTable(this Database db, bool overwrite, Type modelType)
{
var tableNameAttribute = modelType.FirstAttribute<TableNameAttribute>();
var tableDefinition = DefinitionFactory.GetTableDefinition(modelType);
var tableName = tableDefinition.TableName;
var objProperties = modelType.GetProperties().ToList();
string tableName = tableNameAttribute.Value;
string createSql = SyntaxConfig.SqlSyntaxProvider.ToCreateTableStatement(tableDefinition);
string createPrimaryKeySql = SyntaxConfig.SqlSyntaxProvider.ToCreatePrimaryKeyStatement(tableDefinition);
var foreignSql = SyntaxConfig.SqlSyntaxProvider.ToCreateForeignKeyStatements(tableDefinition);
var indexSql = SyntaxConfig.SqlSyntaxProvider.ToCreateIndexStatements(tableDefinition);
var sql = Sql.Builder.Append(string.Format("CREATE TABLE {0} (", tableName));
var primaryKeyConstraints = new List<Sql>();
var foreignKeyConstraints = new List<Sql>();
var indexes = new List<Sql>();
var sb = new StringBuilder();
foreach (var propertyInfo in objProperties)
#if DEBUG
Console.WriteLine(createSql);
Console.WriteLine(createPrimaryKeySql);
foreach (var sql in foreignSql)
{
//If current property is a ResultColumn then skip it
var resultColumnAttribute = propertyInfo.FirstAttribute<ResultColumnAttribute>();
if(resultColumnAttribute != null)
{
continue;
}
//Assumes ExplicitColumn attribute and thus having a ColumnAttribute with the name of the column
var columnAttribute = propertyInfo.FirstAttribute<ColumnAttribute>();
if(columnAttribute == null) continue;
sb.AppendFormat("[{0}]", columnAttribute.Name);
var databaseTypeAttribute = propertyInfo.FirstAttribute<DatabaseTypeAttribute>();
if (databaseTypeAttribute != null)
{
sb.AppendFormat(" {0}", databaseTypeAttribute.ToSqlSyntax());
}
else
{
//Convetion - Use property's Type to set/find db type
//TODO Improve :)
if(propertyInfo.PropertyType == typeof(string))
{
sb.AppendFormat(" [nvarchar] (255)");
}
else if (propertyInfo.PropertyType == typeof(int))
{
sb.AppendFormat(" [int]");
}
else if (propertyInfo.PropertyType == typeof(int?))
{
sb.AppendFormat(" [int]");
}
else if (propertyInfo.PropertyType == typeof(long))
{
sb.AppendFormat(" [bigint]");
}
else if (propertyInfo.PropertyType == typeof(bool))
{
sb.AppendFormat(" [bit]");
}
else if (propertyInfo.PropertyType == typeof(bool?))
{
sb.AppendFormat(" [bit]");
}
else if (propertyInfo.PropertyType == typeof(byte))
{
sb.AppendFormat(DatabaseFactory.Current.DatabaseProvider == DatabaseProviders.SqlServer
? " [tinyint]"
: " [int]");
}
else if (propertyInfo.PropertyType == typeof(short))
{
sb.AppendFormat(DatabaseFactory.Current.DatabaseProvider == DatabaseProviders.SqlServer
? " [smallint]"
: " [int]");
}
else if (propertyInfo.PropertyType == typeof(DateTime))
{
sb.AppendFormat(" [datetime]");
}
else if (propertyInfo.PropertyType == typeof(DateTime?))
{
sb.AppendFormat(" [datetime]");
}
else if (propertyInfo.PropertyType == typeof(Guid))
{
sb.AppendFormat(" [uniqueidentifier]");
}
else if (propertyInfo.PropertyType == typeof(Guid?))
{
sb.AppendFormat(" [uniqueidentifier]");
}
}
var nullSettingAttribute = propertyInfo.FirstAttribute<NullSettingAttribute>();
if(nullSettingAttribute != null)
{
sb.AppendFormat(" {0}", nullSettingAttribute.ToSqlSyntax());
}
else
{
//Convention - Use "NOT NULL" if nothing is specified
sb.AppendFormat(" {0}", NullSettings.NotNull.ToSqlSyntax());
}
var primaryKeyColumnAttribute = propertyInfo.FirstAttribute<PrimaryKeyColumnAttribute>();
if(primaryKeyColumnAttribute != null)
{
sb.Append(primaryKeyColumnAttribute.ToSqlSyntax());
//Add to list of primary key constraints
primaryKeyConstraints.Add(new Sql(primaryKeyColumnAttribute.ToSqlSyntax(tableName, columnAttribute.Name)));
}
var constraintAttribute = propertyInfo.FirstAttribute<ConstraintAttribute>();
if(constraintAttribute != null)
sb.AppendFormat(" {0}", constraintAttribute.ToSqlSyntax(tableName, columnAttribute.Name));
sb.Append(", ");
//Look for foreign keys
var foreignKeyAttributes = propertyInfo.MultipleAttribute<ForeignKeyAttribute>();
if (foreignKeyAttributes != null)
{
foreignKeyConstraints.AddRange(
foreignKeyAttributes.Select(
attribute => new Sql(attribute.ToSqlSyntax(tableName, columnAttribute.Name))));
}
//Look for indexes
var indexAttribute = propertyInfo.FirstAttribute<IndexAttribute>();
if(indexAttribute != null)
{
indexes.Add(new Sql(indexAttribute.ToSqlSyntax(tableName, columnAttribute.Name)));
}
Console.WriteLine(sql);
}
sql.Append(sb.ToString().TrimEnd(", ".ToCharArray()));
sql.Append(")");//End
foreach (var sql in indexSql)
{
Console.WriteLine(sql);
}
#endif
var tableExist = db.TableExist(tableName);
if(overwrite && tableExist)
if (overwrite && tableExist)
{
db.DropTable(tableName);
}
if(!tableExist)
if (!tableExist)
{
int created = db.Execute(sql);
foreach (var constraint in primaryKeyConstraints)
{
db.Execute(constraint);
}
foreach (var constraint in foreignKeyConstraints)
{
db.Execute(constraint);
}
foreach (var index in indexes)
{
db.Execute(index);
}
}
int created = db.Execute(new Sql(createSql));
#if DEBUG
Console.WriteLine(sql.SQL);
foreach (var constraint in primaryKeyConstraints)
{
Console.WriteLine(constraint.SQL);
if(!string.IsNullOrEmpty(createPrimaryKeySql))
db.Execute(new Sql(createPrimaryKeySql));
foreach (var sql in foreignSql)
{
int createdFk = db.Execute(new Sql(sql));
}
foreach (var sql in indexSql)
{
int createdIndex = db.Execute(new Sql(sql));
}
}
foreach (var constraint in foreignKeyConstraints)
{
Console.WriteLine(constraint.SQL);
}
foreach (var index in indexes)
{
Console.WriteLine(index.SQL);
}
#endif
}
public static void DropTable<T>(this Database db)
@@ -217,17 +85,13 @@ namespace Umbraco.Core.Persistence
public static void DropTable(this Database db, string tableName)
{
var sql = new Sql(string.Format("DROP TABLE {0}", tableName));
var sql = new Sql(string.Format("DROP TABLE {0}", SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(tableName)));
db.Execute(sql);
}
public static bool TableExist(this Database db, string tableName)
{
var scalar =
db.ExecuteScalar<long>("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @tableName",
new {tableName = tableName});
return scalar > 0;
return SyntaxConfig.SqlSyntaxProvider.DoesTableExist(db, tableName);
}
public static void Initialize(this Database db)

View File

@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Data;
namespace Umbraco.Core.Persistence.SqlSyntax
{
internal class DbTypes<TSyntax>
where TSyntax : ISqlSyntaxProvider
{
public DbType DbType;
public string TextDefinition;
public bool ShouldQuoteValue;
public Dictionary<Type, string> ColumnTypeMap = new Dictionary<Type, string>();
public Dictionary<Type, DbType> ColumnDbTypeMap = new Dictionary<Type, DbType>();
public void Set<T>(DbType dbType, string fieldDefinition)
{
DbType = dbType;
TextDefinition = fieldDefinition;
ShouldQuoteValue = fieldDefinition != "INTEGER"
&& fieldDefinition != "BIGINT"
&& fieldDefinition != "DOUBLE"
&& fieldDefinition != "DECIMAL"
&& fieldDefinition != "BOOL";
ColumnTypeMap[typeof(T)] = fieldDefinition;
ColumnDbTypeMap[typeof(T)] = dbType;
}
}
}

View File

@@ -0,0 +1,28 @@
using System;
namespace Umbraco.Core.Persistence.SqlSyntax.ModelDefinitions
{
public class ColumnDefinition
{
public string ColumnName { get; set; }
public Type PropertyType { get; set; }
public string DbType { get; set; }
public int? DbTypeLength { get; set; }
public bool IsNullable { get; set; }
public bool IsPrimaryKey { get; set; }
public bool IsPrimaryKeyIdentityColumn { get; set; }
public bool IsPrimaryKeyClustered { get; set; }
public string PrimaryKeyName { get; set; }
public string PrimaryKeyColumns { get; set; }
public string ConstraintName { get; set; }
public string ConstraintDefaultValue { get; set; }
public bool HasConstraint
{
get { return !string.IsNullOrEmpty(ConstraintName) || !string.IsNullOrEmpty(ConstraintDefaultValue); }
}
}
}

View File

@@ -0,0 +1,112 @@
using System;
using System.Linq;
using Umbraco.Core.Persistence.DatabaseAnnotations;
namespace Umbraco.Core.Persistence.SqlSyntax.ModelDefinitions
{
public static class DefinitionFactory
{
public static TableDefinition GetTableDefinition(Type modelType)
{
var tableNameAttribute = modelType.FirstAttribute<TableNameAttribute>();
string tableName = tableNameAttribute.Value;
var tableDefinition = new TableDefinition { TableName = tableName };
var objProperties = modelType.GetProperties().ToList();
foreach (var propertyInfo in objProperties)
{
//If current property is a ResultColumn then skip it
var resultColumnAttribute = propertyInfo.FirstAttribute<ResultColumnAttribute>();
if (resultColumnAttribute != null) continue;
//Assumes ExplicitColumn attribute and thus having a ColumnAttribute with the name of the column
var columnAttribute = propertyInfo.FirstAttribute<ColumnAttribute>();
if (columnAttribute == null) continue;
//Creates a column definition and adds it to the collection on the table definition
var columnDefinition = new ColumnDefinition
{
ColumnName = columnAttribute.Name,
PropertyType = propertyInfo.PropertyType
};
//Look for specific DbType attributed a column
var databaseTypeAttribute = propertyInfo.FirstAttribute<DatabaseTypeAttribute>();
if (databaseTypeAttribute != null)
{
columnDefinition.DbType = databaseTypeAttribute.DatabaseType.ToString();
if (databaseTypeAttribute.Length > 0)
columnDefinition.DbTypeLength = databaseTypeAttribute.Length;
}
//Look for specific Null setting attributed a column
var nullSettingAttribute = propertyInfo.FirstAttribute<NullSettingAttribute>();
if (nullSettingAttribute != null)
{
columnDefinition.IsNullable = nullSettingAttribute.NullSetting == NullSettings.Null;
}
//Look for Primary Key for the current column
var primaryKeyColumnAttribute = propertyInfo.FirstAttribute<PrimaryKeyColumnAttribute>();
if (primaryKeyColumnAttribute != null)
{
columnDefinition.IsPrimaryKey = true;
columnDefinition.IsPrimaryKeyIdentityColumn = primaryKeyColumnAttribute.AutoIncrement;
columnDefinition.IsPrimaryKeyClustered = primaryKeyColumnAttribute.Clustered;
columnDefinition.PrimaryKeyName = primaryKeyColumnAttribute.Name ?? string.Empty;
columnDefinition.PrimaryKeyColumns = primaryKeyColumnAttribute.OnColumns ?? string.Empty;
}
//Look for Constraint for the current column
var constraintAttribute = propertyInfo.FirstAttribute<ConstraintAttribute>();
if (constraintAttribute != null)
{
columnDefinition.ConstraintName = constraintAttribute.Name ?? string.Empty;
columnDefinition.ConstraintDefaultValue = constraintAttribute.Default ?? string.Empty;
}
tableDefinition.ColumnDefinitions.Add(columnDefinition);
//Creates a foreignkey definition and adds it to the collection on the table definition
var foreignKeyAttributes = propertyInfo.MultipleAttribute<ForeignKeyAttribute>();
if (foreignKeyAttributes != null)
{
foreach (var foreignKeyAttribute in foreignKeyAttributes)
{
var referencedTable = foreignKeyAttribute.Type.FirstAttribute<TableNameAttribute>();
var referencedPrimaryKey = foreignKeyAttribute.Type.FirstAttribute<PrimaryKeyAttribute>();
string referencedColumn = string.IsNullOrEmpty(foreignKeyAttribute.Column)
? referencedPrimaryKey.Value
: foreignKeyAttribute.Column;
var foreignKeyDefinition = new ForeignKeyDefinition
{
ColumnName = columnAttribute.Name,
ConstraintName = foreignKeyAttribute.Name,
ReferencedColumnName = referencedColumn,
ReferencedTableName = referencedTable.Value
};
tableDefinition.ForeignKeyDefinitions.Add(foreignKeyDefinition);
}
}
//Creates an index definition and adds it to the collection on the table definition
var indexAttribute = propertyInfo.FirstAttribute<IndexAttribute>();
if (indexAttribute != null)
{
var indexDefinition = new IndexDefinition
{
ColumnNames = indexAttribute.ForColumns,
IndexName = indexAttribute.Name,
IndexType = indexAttribute.IndexType,
IndexForColumn = columnAttribute.Name
};
tableDefinition.IndexDefinitions.Add(indexDefinition);
}
}
return tableDefinition;
}
}
}

View File

@@ -0,0 +1,10 @@
namespace Umbraco.Core.Persistence.SqlSyntax.ModelDefinitions
{
public class ForeignKeyDefinition
{
public string ConstraintName { get; set; }
public string ColumnName { get; set; }
public string ReferencedTableName { get; set; }
public string ReferencedColumnName { get; set; }
}
}

View File

@@ -0,0 +1,12 @@
using Umbraco.Core.Persistence.DatabaseAnnotations;
namespace Umbraco.Core.Persistence.SqlSyntax.ModelDefinitions
{
public class IndexDefinition
{
public string IndexName { get; set; }
public IndexTypes IndexType { get; set; }
public string ColumnNames { get; set; }
public string IndexForColumn { get; set; }
}
}

View File

@@ -0,0 +1,33 @@
using System.Collections.Generic;
using System.Linq;
namespace Umbraco.Core.Persistence.SqlSyntax.ModelDefinitions
{
public class TableDefinition
{
public TableDefinition()
{
ColumnDefinitions = new List<ColumnDefinition>();
ForeignKeyDefinitions = new List<ForeignKeyDefinition>();
IndexDefinitions = new List<IndexDefinition>();
}
public string TableName { get; set; }
public bool IsPrimaryKeyClustered
{
get { return ColumnDefinitions.Any(x => x.IsPrimaryKeyClustered); }
}
public string PrimaryKeyName
{
get { return ColumnDefinitions.First(x => x.IsPrimaryKey).PrimaryKeyName ?? string.Empty; }
}
public string PrimaryKeyColumns
{
get { return ColumnDefinitions.First(x => x.IsPrimaryKey).PrimaryKeyColumns ?? string.Empty; }
}
public List<ColumnDefinition> ColumnDefinitions { get; set; }
public List<ForeignKeyDefinition> ForeignKeyDefinitions { get; set; }
public List<IndexDefinition> IndexDefinitions { get; set; }
}
}

View File

@@ -0,0 +1,54 @@
using Umbraco.Core.Persistence.SqlSyntax.ModelDefinitions;
namespace Umbraco.Core.Persistence.SqlSyntax
{
internal static class MySqlSyntax
{
public static ISqlSyntaxProvider Provider { get { return MySqlSyntaxProvider.Instance; } }
}
internal class MySqlSyntaxProvider : SqlSyntaxProviderBase<MySqlSyntaxProvider>
{
public static MySqlSyntaxProvider Instance = new MySqlSyntaxProvider();
private MySqlSyntaxProvider()
{
AutoIncrementDefinition = "AUTO_INCREMENT";
IntColumnDefinition = "int(11)";
BoolColumnDefinition = "tinyint(1)";
TimeColumnDefinition = "time";
DecimalColumnDefinition = "decimal(38,6)";
GuidColumnDefinition = "char(32)";
DefaultStringLength = 255;
InitColumnTypeMap();
DefaultValueFormat = " DEFAULT '{0}'";
}
public override string GetQuotedTableName(string tableName)
{
return string.Format("`{0}`", tableName);
}
public override string GetQuotedColumnName(string columnName)
{
return string.Format("`{0}`", columnName);
}
public override string GetQuotedName(string name)
{
return string.Format("`{0}`", name);
}
public override bool DoesTableExist(Database db, string tableName)
{
var result =
db.ExecuteScalar<long>("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES " +
"WHERE TABLE_NAME = @TableName AND " +
"TABLE_SCHEMA = @TableSchema", new { TableName = tableName, TableSchema = db.Connection.Database });
return result > 0;
}
}
}

View File

@@ -0,0 +1,68 @@
using Umbraco.Core.Persistence.SqlSyntax.ModelDefinitions;
namespace Umbraco.Core.Persistence.SqlSyntax
{
internal class SqlCeSyntaxProvider : SqlSyntaxProviderBase<SqlCeSyntaxProvider>
{
public static SqlCeSyntaxProvider Instance = new SqlCeSyntaxProvider();
private SqlCeSyntaxProvider()
{
StringLengthColumnDefinitionFormat = StringLengthUnicodeColumnDefinitionFormat;
StringColumnDefinition = string.Format(StringLengthColumnDefinitionFormat, DefaultStringLength);
AutoIncrementDefinition = "IDENTITY(1,1)";
StringColumnDefinition = "NVARCHAR(255)";
GuidColumnDefinition = "UniqueIdentifier";
RealColumnDefinition = "FLOAT";
BoolColumnDefinition = "BIT";
DecimalColumnDefinition = "DECIMAL(38,6)";
TimeColumnDefinition = "TIME"; //SQLSERVER 2008+
BlobColumnDefinition = "VARBINARY(MAX)";
InitColumnTypeMap();
}
public override string GetQuotedTableName(string tableName)
{
return string.Format("[{0}]", tableName);
}
public override string GetQuotedColumnName(string columnName)
{
return string.Format("[{0}]", columnName);
}
public override string GetQuotedName(string name)
{
return string.Format("[{0}]", name);
}
public override string GetPrimaryKeyStatement(ColumnDefinition column, string tableName)
{
string constraintName = string.IsNullOrEmpty(column.PrimaryKeyName)
? string.Format("PK_{0}", tableName)
: column.PrimaryKeyName;
string columns = string.IsNullOrEmpty(column.PrimaryKeyColumns)
? GetQuotedColumnName(column.ColumnName)
: column.PrimaryKeyColumns;
string sql = string.Format("ALTER TABLE {0} ADD CONSTRAINT {1} PRIMARY KEY ({2}); \n",
GetQuotedTableName(tableName),
GetQuotedName(constraintName),
columns);
return sql;
}
public override bool DoesTableExist(Database db, string tableName)
{
var result =
db.ExecuteScalar<long>("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @TableName",
new { TableName = tableName });
return result > 0;
}
}
}

View File

@@ -0,0 +1,35 @@
using Umbraco.Core.Persistence.SqlSyntax.ModelDefinitions;
namespace Umbraco.Core.Persistence.SqlSyntax
{
internal class SqlServerSyntaxProvider : SqlSyntaxProviderBase<SqlServerSyntaxProvider>
{
public static SqlServerSyntaxProvider Instance = new SqlServerSyntaxProvider();
private SqlServerSyntaxProvider()
{
StringLengthColumnDefinitionFormat = StringLengthUnicodeColumnDefinitionFormat;
StringColumnDefinition = string.Format(StringLengthColumnDefinitionFormat, DefaultStringLength);
AutoIncrementDefinition = "IDENTITY(1,1)";
StringColumnDefinition = "VARCHAR(8000)";
GuidColumnDefinition = "UniqueIdentifier";
RealColumnDefinition = "FLOAT";
BoolColumnDefinition = "BIT";
DecimalColumnDefinition = "DECIMAL(38,6)";
TimeColumnDefinition = "TIME"; //SQLSERVER 2008+
BlobColumnDefinition = "VARBINARY(MAX)";
InitColumnTypeMap();
}
public override bool DoesTableExist(Database db, string tableName)
{
var result =
db.ExecuteScalar<long>("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @TableName",
new { TableName = tableName });
return result > 0;
}
}
}

View File

@@ -0,0 +1,277 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.SqlSyntax.ModelDefinitions;
namespace Umbraco.Core.Persistence.SqlSyntax
{
public interface ISqlSyntaxProvider
{
string GetQuotedTableName(string tableName);
string GetQuotedColumnName(string columnName);
string GetQuotedName(string name);
bool DoesTableExist(Database db, string tableName);
string ToCreateTableStatement(TableDefinition tableDefinition);
List<string> ToCreateForeignKeyStatements(TableDefinition tableDefinition);
List<string> ToCreateIndexStatements(TableDefinition tableDefinition);
DbType GetColumnDbType(Type valueType);
string GetIndexType(IndexTypes indexTypes);
string GetColumnDefinition(ColumnDefinition column, string tableName);
string GetPrimaryKeyStatement(ColumnDefinition column, string tableName);
string ToCreatePrimaryKeyStatement(TableDefinition table);
}
internal abstract class SqlSyntaxProviderBase<TSyntax> : ISqlSyntaxProvider
where TSyntax : ISqlSyntaxProvider
{
public string StringLengthNonUnicodeColumnDefinitionFormat = "VARCHAR({0})";
public string StringLengthUnicodeColumnDefinitionFormat = "NVARCHAR({0})";
public string DefaultValueFormat = " DEFAULT ({0})";
public int DefaultStringLength = 255;
//Set by Constructor
public string StringColumnDefinition;
public string StringLengthColumnDefinitionFormat;
public string AutoIncrementDefinition = "AUTOINCREMENT";
public string IntColumnDefinition = "INTEGER";
public string LongColumnDefinition = "BIGINT";
public string GuidColumnDefinition = "GUID";
public string BoolColumnDefinition = "BOOL";
public string RealColumnDefinition = "DOUBLE";
public string DecimalColumnDefinition = "DECIMAL";
public string BlobColumnDefinition = "BLOB";
public string DateTimeColumnDefinition = "DATETIME";
public string TimeColumnDefinition = "DATETIME";
protected DbTypes<TSyntax> DbTypeMap = new DbTypes<TSyntax>();
protected void InitColumnTypeMap()
{
DbTypeMap.Set<string>(DbType.String, StringColumnDefinition);
DbTypeMap.Set<char>(DbType.StringFixedLength, StringColumnDefinition);
DbTypeMap.Set<char?>(DbType.StringFixedLength, StringColumnDefinition);
DbTypeMap.Set<char[]>(DbType.String, StringColumnDefinition);
DbTypeMap.Set<bool>(DbType.Boolean, BoolColumnDefinition);
DbTypeMap.Set<bool?>(DbType.Boolean, BoolColumnDefinition);
DbTypeMap.Set<Guid>(DbType.Guid, GuidColumnDefinition);
DbTypeMap.Set<Guid?>(DbType.Guid, GuidColumnDefinition);
DbTypeMap.Set<DateTime>(DbType.DateTime, DateTimeColumnDefinition);
DbTypeMap.Set<DateTime?>(DbType.DateTime, DateTimeColumnDefinition);
DbTypeMap.Set<TimeSpan>(DbType.Time, TimeColumnDefinition);
DbTypeMap.Set<TimeSpan?>(DbType.Time, TimeColumnDefinition);
DbTypeMap.Set<DateTimeOffset>(DbType.Time, TimeColumnDefinition);
DbTypeMap.Set<DateTimeOffset?>(DbType.Time, TimeColumnDefinition);
DbTypeMap.Set<byte>(DbType.Byte, IntColumnDefinition);
DbTypeMap.Set<byte?>(DbType.Byte, IntColumnDefinition);
DbTypeMap.Set<sbyte>(DbType.SByte, IntColumnDefinition);
DbTypeMap.Set<sbyte?>(DbType.SByte, IntColumnDefinition);
DbTypeMap.Set<short>(DbType.Int16, IntColumnDefinition);
DbTypeMap.Set<short?>(DbType.Int16, IntColumnDefinition);
DbTypeMap.Set<ushort>(DbType.UInt16, IntColumnDefinition);
DbTypeMap.Set<ushort?>(DbType.UInt16, IntColumnDefinition);
DbTypeMap.Set<int>(DbType.Int32, IntColumnDefinition);
DbTypeMap.Set<int?>(DbType.Int32, IntColumnDefinition);
DbTypeMap.Set<uint>(DbType.UInt32, IntColumnDefinition);
DbTypeMap.Set<uint?>(DbType.UInt32, IntColumnDefinition);
DbTypeMap.Set<long>(DbType.Int64, LongColumnDefinition);
DbTypeMap.Set<long?>(DbType.Int64, LongColumnDefinition);
DbTypeMap.Set<ulong>(DbType.UInt64, LongColumnDefinition);
DbTypeMap.Set<ulong?>(DbType.UInt64, LongColumnDefinition);
DbTypeMap.Set<float>(DbType.Single, RealColumnDefinition);
DbTypeMap.Set<float?>(DbType.Single, RealColumnDefinition);
DbTypeMap.Set<double>(DbType.Double, RealColumnDefinition);
DbTypeMap.Set<double?>(DbType.Double, RealColumnDefinition);
DbTypeMap.Set<decimal>(DbType.Decimal, DecimalColumnDefinition);
DbTypeMap.Set<decimal?>(DbType.Decimal, DecimalColumnDefinition);
DbTypeMap.Set<byte[]>(DbType.Binary, BlobColumnDefinition);
}
public virtual string GetQuotedTableName(string tableName)
{
return string.Format("\"{0}\"", tableName);
}
public virtual string GetQuotedColumnName(string columnName)
{
return string.Format("\"{0}\"", columnName);
}
public virtual string GetQuotedName(string name)
{
return string.Format("\"{0}\"", name);
}
public virtual string GetIndexType(IndexTypes indexTypes)
{
string indexType;
if (indexTypes == IndexTypes.Clustered)
{
indexType = "CLUSTERED";
}
else
{
indexType = indexTypes == IndexTypes.NonClustered
? "NONCLUSTERED"
: "UNIQUE NONCLUSTERED";
}
return indexType;
}
public virtual string GetColumnDefinition(ColumnDefinition column, string tableName)
{
string dbTypeDefinition;
if(!string.IsNullOrEmpty(column.DbType))
{
dbTypeDefinition = column.DbType;//Translate
if (column.DbTypeLength.HasValue)
dbTypeDefinition = string.Format("{0}({1})", column.DbType, column.DbTypeLength.Value);
}
else if (column.PropertyType == typeof(string))
{
dbTypeDefinition = string.Format(StringLengthColumnDefinitionFormat, column.DbTypeLength.GetValueOrDefault(DefaultStringLength));
}
else
{
if (!DbTypeMap.ColumnTypeMap.TryGetValue(column.PropertyType, out dbTypeDefinition))
{
dbTypeDefinition = "";
}
}
var sql = new StringBuilder();
sql.AppendFormat("{0} {1}", GetQuotedColumnName(column.ColumnName), dbTypeDefinition);
if (column.IsPrimaryKeyIdentityColumn)
{
sql.Append(" NOT NULL ").Append(AutoIncrementDefinition);
}
else
{
sql.Append(column.IsNullable ? " NULL" : " NOT NULL");
}
if(column.HasConstraint)
{
sql.AppendFormat(" CONSTRAINT {0}",
string.IsNullOrEmpty(column.ConstraintName)
? GetQuotedName(string.Format("DF_{0}_{1}", tableName, column.ColumnName))
: column.ConstraintName);
sql.AppendFormat(DefaultValueFormat, column.ConstraintDefaultValue);
}
return sql.ToString();
}
public virtual string GetPrimaryKeyStatement(ColumnDefinition column, string tableName)
{
string constraintName = string.IsNullOrEmpty(column.PrimaryKeyName)
? string.Format("PK_{0}", tableName)
: column.PrimaryKeyName;
string columns = string.IsNullOrEmpty(column.PrimaryKeyColumns)
? GetQuotedColumnName(column.ColumnName)
: column.PrimaryKeyColumns;
string sql = string.Format("ALTER TABLE {0} ADD CONSTRAINT {1} PRIMARY KEY {2} ({3}); \n",
GetQuotedTableName(tableName),
GetQuotedName(constraintName),
column.IsPrimaryKeyClustered ? "CLUSTERED" : "NONCLUSTERED",
columns);
return sql;
}
public virtual string ToCreateTableStatement(TableDefinition table)
{
var columns = new StringBuilder();
foreach (var column in table.ColumnDefinitions)
{
columns.Append(GetColumnDefinition(column, table.TableName) + ", \n");
}
string sql = string.Format("CREATE TABLE {0} \n(\n {1} \n); \n",
table.TableName,
columns.ToString().TrimEnd(", \n".ToCharArray()));
return sql;
}
public virtual string ToCreatePrimaryKeyStatement(TableDefinition table)
{
var columnDefinition = table.ColumnDefinitions.FirstOrDefault(x => x.IsPrimaryKey);
if (columnDefinition == null)
return string.Empty;
var sql = GetPrimaryKeyStatement(columnDefinition, table.TableName);
return sql;
}
public virtual List<string> ToCreateForeignKeyStatements(TableDefinition table)
{
var foreignKeys = new List<string>();
foreach (var key in table.ForeignKeyDefinitions)
{
string constraintName = string.IsNullOrEmpty(key.ConstraintName)
? string.Format("FK_{0}_{1}_{2}", table.TableName, key.ReferencedTableName, key.ReferencedColumnName)
: key.ConstraintName;
foreignKeys.Add(string.Format("ALTER TABLE {0} ADD CONSTRAINT {1} FOREIGN KEY ({2}) REFERENCES {3} ({4}); \n",
GetQuotedTableName(table.TableName),
GetQuotedName(constraintName),
GetQuotedColumnName(key.ColumnName),
GetQuotedTableName(key.ReferencedTableName),
GetQuotedColumnName(key.ReferencedColumnName)));
}
return foreignKeys;
}
public virtual List<string> ToCreateIndexStatements(TableDefinition table)
{
var indexes = new List<string>();
foreach (var index in table.IndexDefinitions)
{
string name = string.IsNullOrEmpty(index.IndexName)
? string.Format("IX_{0}_{1}", table.TableName, index.IndexForColumn)
: index.IndexName;
string columns = string.IsNullOrEmpty(index.ColumnNames)
? GetQuotedColumnName(index.IndexForColumn)
: index.ColumnNames;
indexes.Add(string.Format("CREATE {0} INDEX {1} ON {2} ({3}); \n",
GetIndexType(index.IndexType),
GetQuotedName(name),
GetQuotedTableName(table.TableName),
columns));
}
return indexes;
}
public virtual bool DoesTableExist(Database db, string tableName)
{
return false;
}
public virtual DbType GetColumnDbType(Type valueType)
{
if (valueType.IsEnum)
return DbTypeMap.ColumnDbTypeMap[typeof(string)];
return DbTypeMap.ColumnDbTypeMap[valueType];
}
}
}

View File

@@ -0,0 +1,23 @@
using System;
namespace Umbraco.Core.Persistence.SqlSyntax
{
internal static class SyntaxConfig
{
private static ISqlSyntaxProvider _sqlSyntaxProvider;
public static ISqlSyntaxProvider SqlSyntaxProvider
{
get
{
if(_sqlSyntaxProvider == null)
{
throw new ArgumentNullException("SqlSyntaxProvider",
"You must set the singleton 'Umbraco.Core.Persistence.SqlSyntax.SyntaxConfig' to use an sql syntax provider");
}
return _sqlSyntaxProvider;
}
set { _sqlSyntaxProvider = value; }
}
}
}

View File

@@ -104,7 +104,6 @@
<Compile Include="Persistence\Caching\IRepositoryCacheProvider.cs" />
<Compile Include="Persistence\Caching\NullCacheProvider.cs" />
<Compile Include="Persistence\Caching\RuntimeCacheProvider.cs" />
<Compile Include="Persistence\DatabaseAnnotations\AttributeExtensions.cs" />
<Compile Include="Persistence\DatabaseAnnotations\ConstraintAttribute.cs" />
<Compile Include="Persistence\DatabaseAnnotations\DatabaseTypeAttribute.cs" />
<Compile Include="Persistence\DatabaseAnnotations\DatabaseTypes.cs" />
@@ -172,6 +171,17 @@
<Compile Include="Persistence\Repositories\StylesheetRepository.cs" />
<Compile Include="Persistence\Repositories\TemplateRepository.cs" />
<Compile Include="Persistence\RepositoryResolver.cs" />
<Compile Include="Persistence\SqlSyntax\DbTypes.cs" />
<Compile Include="Persistence\SqlSyntax\ModelDefinitions\ColumnDefinition.cs" />
<Compile Include="Persistence\SqlSyntax\ModelDefinitions\DefinitionFactory.cs" />
<Compile Include="Persistence\SqlSyntax\ModelDefinitions\ForeignKeyDefinition.cs" />
<Compile Include="Persistence\SqlSyntax\ModelDefinitions\IndexDefinition.cs" />
<Compile Include="Persistence\SqlSyntax\ModelDefinitions\TableDefinition.cs" />
<Compile Include="Persistence\SqlSyntax\MySqlSyntaxProvider.cs" />
<Compile Include="Persistence\SqlSyntax\SqlCeSyntaxProvider.cs" />
<Compile Include="Persistence\SqlSyntax\SqlServerSyntaxProvider.cs" />
<Compile Include="Persistence\SqlSyntax\SqlSyntaxProviderBase.cs" />
<Compile Include="Persistence\SqlSyntax\SyntaxConfig.cs" />
<Compile Include="Persistence\TransactionType.cs" />
<Compile Include="Persistence\UnitOfWork\FileUnitOfWork.cs" />
<Compile Include="Persistence\UnitOfWork\FileUnitOfWorkProvider.cs" />

View File

@@ -5,6 +5,7 @@ using System.IO;
using NUnit.Framework;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Tests.TestHelpers;
namespace Umbraco.Tests.Persistence
@@ -37,6 +38,8 @@ namespace Umbraco.Tests.Persistence
var engine = new SqlCeEngine(settings.ConnectionString);
engine.CreateDatabase();
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntaxProvider.Instance;
//Create the umbraco database
//DatabaseFactory.Current.Database.Initialize();
}

View File

@@ -0,0 +1,42 @@
using NUnit.Framework;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Tests.TestHelpers;
namespace Umbraco.Tests.Persistence
{
[TestFixture]
public class MySqlDatabaseCreationTest : BaseDatabaseTest
{
#region Overrides of BaseDatabaseTest
public override string ConnectionString
{
get { return "Server = 192.168.1.5; Database = testDb; Uid = umbraco; Pwd = umbraco"; }
}
public override string ProviderName
{
get { return "MySql.Data.MySqlClient"; }
}
public override ISqlSyntaxProvider SyntaxProvider
{
get { return MySqlSyntaxProvider.Instance; }
}
#endregion
[Test]
public void Can_Assert_Created_Database()
{
bool umbracoNodeTable = Database.TableExist("umbracoNode");
bool umbracoUserTable = Database.TableExist("umbracoUser");
bool cmsTagsTable = Database.TableExist("cmsTags");
Assert.That(umbracoNodeTable, Is.True);
Assert.That(umbracoUserTable, Is.True);
Assert.That(cmsTagsTable, Is.True);
}
}
}

View File

@@ -3,6 +3,7 @@ using System.Data.SqlServerCe;
using System.IO;
using NUnit.Framework;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Tests.TestHelpers
{
@@ -38,6 +39,8 @@ namespace Umbraco.Tests.TestHelpers
engine.CreateDatabase();
}
SyntaxConfig.SqlSyntaxProvider = SyntaxProvider;
//Create the umbraco database
_database = new Database(ConnectionString, ProviderName);
_database.Initialize();
@@ -45,6 +48,7 @@ namespace Umbraco.Tests.TestHelpers
public abstract string ConnectionString { get; }
public abstract string ProviderName { get; }
public abstract ISqlSyntaxProvider SyntaxProvider { get; }
protected Database Database
{

View File

@@ -52,6 +52,10 @@
<Reference Include="log4net, Version=1.2.11.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\log4net.2.0.0\lib\net40-full\log4net.dll</HintPath>
</Reference>
<Reference Include="MySql.Data, Version=5.1.2.2, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\lib\MySql.Data.dll</HintPath>
</Reference>
<Reference Include="nunit.framework">
<HintPath>..\packages\NUnit.2.6.0.12054\lib\nunit.framework.dll</HintPath>
</Reference>
@@ -92,6 +96,7 @@
<Compile Include="Models\StylesheetTests.cs" />
<Compile Include="Persistence\DatabaseExtensionsTest.cs" />
<Compile Include="Persistence\DatabaseFactoryTests.cs" />
<Compile Include="Persistence\MySqlDatabaseCreationTest.cs" />
<Compile Include="Persistence\RepositoryResolverTests.cs" />
<Compile Include="Resolvers\ActionsResolverTests.cs" />
<Compile Include="AsynchronousRollingFileAppenderTests.cs" />