diff --git a/src/Umbraco.Infrastructure/Persistence/DatabaseAnnotations/SpecialDbType.cs b/src/Umbraco.Infrastructure/Persistence/DatabaseAnnotations/SpecialDbType.cs
new file mode 100644
index 0000000000..00be5c51ab
--- /dev/null
+++ b/src/Umbraco.Infrastructure/Persistence/DatabaseAnnotations/SpecialDbType.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+
+namespace Umbraco.Cms.Infrastructure.Persistence.DatabaseAnnotations
+{
+ ///
+ /// Allows for specifying custom DB types that are not natively mapped.
+ ///
+ public struct SpecialDbType : IEquatable
+ {
+ private readonly string _dbType;
+
+ public SpecialDbType(string dbType)
+ {
+ if (string.IsNullOrWhiteSpace(dbType))
+ {
+ throw new ArgumentException($"'{nameof(dbType)}' cannot be null or whitespace.", nameof(dbType));
+ }
+
+ _dbType = dbType;
+ }
+
+ public SpecialDbType(SpecialDbTypes specialDbTypes)
+ => _dbType = specialDbTypes.ToString();
+
+ public static SpecialDbType NTEXT { get; } = new SpecialDbType(SpecialDbTypes.NTEXT);
+ public static SpecialDbType NCHAR { get; } = new SpecialDbType(SpecialDbTypes.NCHAR);
+ public static SpecialDbType NVARCHARMAX { get; } = new SpecialDbType(SpecialDbTypes.NVARCHARMAX);
+
+ public override bool Equals(object obj) => obj is SpecialDbType types && Equals(types);
+ public bool Equals(SpecialDbType other) => _dbType == other._dbType;
+ public override int GetHashCode() => 1038481724 + EqualityComparer.Default.GetHashCode(_dbType);
+
+ public override string ToString() => _dbType.ToString();
+
+ // Make this directly castable to string
+ public static implicit operator string(SpecialDbType dbType) => dbType.ToString();
+
+ // direct equality operators with SpecialDbTypes enum
+ public static bool operator ==(SpecialDbTypes x, SpecialDbType y) => x.ToString() == y;
+ public static bool operator !=(SpecialDbTypes x, SpecialDbType y) => x.ToString() != y;
+ }
+}
diff --git a/src/Umbraco.Infrastructure/Persistence/DatabaseAnnotations/SpecialDbTypeAttribute.cs b/src/Umbraco.Infrastructure/Persistence/DatabaseAnnotations/SpecialDbTypeAttribute.cs
index 158a7ccb9b..d7fd2ff34f 100644
--- a/src/Umbraco.Infrastructure/Persistence/DatabaseAnnotations/SpecialDbTypeAttribute.cs
+++ b/src/Umbraco.Infrastructure/Persistence/DatabaseAnnotations/SpecialDbTypeAttribute.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
namespace Umbraco.Cms.Infrastructure.Persistence.DatabaseAnnotations
{
@@ -12,13 +12,14 @@ namespace Umbraco.Cms.Infrastructure.Persistence.DatabaseAnnotations
public class SpecialDbTypeAttribute : Attribute
{
public SpecialDbTypeAttribute(SpecialDbTypes databaseType)
- {
- DatabaseType = databaseType;
- }
+ => DatabaseType = new SpecialDbType(databaseType);
+
+ public SpecialDbTypeAttribute(string databaseType)
+ => DatabaseType = new SpecialDbType(databaseType);
///
- /// Gets or sets the for this column
+ /// Gets or sets the for this column
///
- public SpecialDbTypes DatabaseType { get; private set; }
+ public SpecialDbType DatabaseType { get; private set; }
}
}
diff --git a/src/Umbraco.Infrastructure/Persistence/DatabaseAnnotations/SpecialDbTypes.cs b/src/Umbraco.Infrastructure/Persistence/DatabaseAnnotations/SpecialDbTypes.cs
index 9d07395743..d867d6f682 100644
--- a/src/Umbraco.Infrastructure/Persistence/DatabaseAnnotations/SpecialDbTypes.cs
+++ b/src/Umbraco.Infrastructure/Persistence/DatabaseAnnotations/SpecialDbTypes.cs
@@ -1,13 +1,12 @@
namespace Umbraco.Cms.Infrastructure.Persistence.DatabaseAnnotations
{
///
- /// Enum with the two special types that has to be supported because
- /// of the current umbraco db schema.
+ /// Known special DB types required for Umbraco.
///
public enum SpecialDbTypes
{
NTEXT,
NCHAR,
- NVARCHARMAX
+ NVARCHARMAX,
}
}
diff --git a/src/Umbraco.Infrastructure/Persistence/DatabaseModelDefinitions/ColumnDefinition.cs b/src/Umbraco.Infrastructure/Persistence/DatabaseModelDefinitions/ColumnDefinition.cs
index 2c22863ae5..dee560a40d 100644
--- a/src/Umbraco.Infrastructure/Persistence/DatabaseModelDefinitions/ColumnDefinition.cs
+++ b/src/Umbraco.Infrastructure/Persistence/DatabaseModelDefinitions/ColumnDefinition.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Data;
using Umbraco.Cms.Infrastructure.Persistence.DatabaseAnnotations;
@@ -12,9 +12,12 @@ namespace Umbraco.Cms.Infrastructure.Persistence.DatabaseModelDefinitions
//When DbType isn't set explicitly the Type will be used to find the right DbType in the SqlSyntaxProvider.
//This type is typically used as part of an initial table creation
public Type PropertyType { get; set; }
- //Only used for special cases as part of an initial table creation
- public bool HasSpecialDbType { get; set; }
- public SpecialDbTypes DbType { get; set; }
+
+ ///
+ /// Used for column types that cannot be natively mapped.
+ ///
+ public SpecialDbType? CustomDbType { get; set; }
+
public virtual int Seeding { get; set; }
public virtual int Size { get; set; }
public virtual int Precision { get; set; }
diff --git a/src/Umbraco.Infrastructure/Persistence/DatabaseModelDefinitions/DefinitionFactory.cs b/src/Umbraco.Infrastructure/Persistence/DatabaseModelDefinitions/DefinitionFactory.cs
index 407672c995..34ad767b04 100644
--- a/src/Umbraco.Infrastructure/Persistence/DatabaseModelDefinitions/DefinitionFactory.cs
+++ b/src/Umbraco.Infrastructure/Persistence/DatabaseModelDefinitions/DefinitionFactory.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Linq;
using System.Reflection;
using NPoco;
@@ -75,8 +75,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.DatabaseModelDefinitions
var databaseTypeAttribute = propertyInfo.FirstAttribute();
if (databaseTypeAttribute != null)
{
- definition.HasSpecialDbType = true;
- definition.DbType = databaseTypeAttribute.DatabaseType;
+ definition.CustomDbType = databaseTypeAttribute.DatabaseType;
}
else
{
diff --git a/src/Umbraco.Infrastructure/Persistence/DbProviderFactoryCreator.cs b/src/Umbraco.Infrastructure/Persistence/DbProviderFactoryCreator.cs
index 797400b7cc..942368f5cb 100644
--- a/src/Umbraco.Infrastructure/Persistence/DbProviderFactoryCreator.cs
+++ b/src/Umbraco.Infrastructure/Persistence/DbProviderFactoryCreator.cs
@@ -24,15 +24,16 @@ namespace Umbraco.Cms.Infrastructure.Persistence
IEnumerable providerSpecificMapperFactories)
{
_getFactory = getFactory;
- _embeddedDatabaseCreators = embeddedDatabaseCreators.ToDictionary(x=>x.ProviderName);
- _syntaxProviders = syntaxProviders.ToDictionary(x=>x.ProviderName);
- _bulkSqlInsertProviders = bulkSqlInsertProviders.ToDictionary(x=>x.ProviderName);
- _providerSpecificMapperFactories = providerSpecificMapperFactories.ToDictionary(x=>x.ProviderName);
+ _embeddedDatabaseCreators = embeddedDatabaseCreators.ToDictionary(x => x.ProviderName);
+ _syntaxProviders = syntaxProviders.ToDictionary(x => x.ProviderName);
+ _bulkSqlInsertProviders = bulkSqlInsertProviders.ToDictionary(x => x.ProviderName);
+ _providerSpecificMapperFactories = providerSpecificMapperFactories.ToDictionary(x => x.ProviderName);
}
public DbProviderFactory CreateFactory(string providerName)
{
- if (string.IsNullOrEmpty(providerName)) return null;
+ if (string.IsNullOrEmpty(providerName))
+ return null;
return _getFactory(providerName);
}
@@ -40,7 +41,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence
public ISqlSyntaxProvider GetSqlSyntaxProvider(string providerName)
{
- if(!_syntaxProviders.TryGetValue(providerName, out var result))
+ if (!_syntaxProviders.TryGetValue(providerName, out var result))
{
throw new InvalidOperationException($"Unknown provider name \"{providerName}\"");
}
@@ -51,7 +52,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence
public IBulkSqlInsertProvider CreateBulkSqlInsertProvider(string providerName)
{
- if(!_bulkSqlInsertProviders.TryGetValue(providerName, out var result))
+ if (!_bulkSqlInsertProviders.TryGetValue(providerName, out var result))
{
return new BasicBulkSqlInsertProvider();
}
@@ -61,7 +62,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence
public void CreateDatabase(string providerName)
{
- if(_embeddedDatabaseCreators.TryGetValue(providerName, out var creator))
+ if (_embeddedDatabaseCreators.TryGetValue(providerName, out var creator))
{
creator.Create();
}
@@ -69,7 +70,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence
public NPocoMapperCollection ProviderSpecificMappers(string providerName)
{
- if(_providerSpecificMapperFactories.TryGetValue(providerName, out var mapperFactory))
+ if (_providerSpecificMapperFactories.TryGetValue(providerName, out var mapperFactory))
{
return mapperFactory.Mappers;
}
diff --git a/src/Umbraco.Infrastructure/Persistence/PocoDataDataReader.cs b/src/Umbraco.Infrastructure/Persistence/PocoDataDataReader.cs
index 71e22a4837..71e249a836 100644
--- a/src/Umbraco.Infrastructure/Persistence/PocoDataDataReader.cs
+++ b/src/Umbraco.Infrastructure/Persistence/PocoDataDataReader.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
@@ -6,6 +6,7 @@ using NPoco;
using Umbraco.Cms.Infrastructure.Persistence.DatabaseAnnotations;
using Umbraco.Cms.Infrastructure.Persistence.DatabaseModelDefinitions;
using Umbraco.Cms.Infrastructure.Persistence.SqlSyntax;
+using Umbraco.Extensions;
namespace Umbraco.Cms.Infrastructure.Persistence
{
@@ -68,22 +69,22 @@ namespace Umbraco.Cms.Infrastructure.Persistence
foreach (var col in _columnDefinitions)
{
SqlDbType sqlDbType;
- if (col.HasSpecialDbType)
+ if (col.CustomDbType.HasValue)
{
//get the SqlDbType from the 'special type'
- switch (col.DbType)
+ switch (col.CustomDbType)
{
- case SpecialDbTypes.NTEXT:
+ case var x when x == SpecialDbType.NTEXT:
sqlDbType = SqlDbType.NText;
break;
- case SpecialDbTypes.NCHAR:
+ case var x when x == SpecialDbType.NCHAR:
sqlDbType = SqlDbType.NChar;
break;
- case SpecialDbTypes.NVARCHARMAX:
+ case var x when x == SpecialDbType.NVARCHARMAX:
sqlDbType = SqlDbType.NVarChar;
break;
default:
- throw new ArgumentOutOfRangeException();
+ throw new ArgumentOutOfRangeException("The custom DB type " + col.CustomDbType + " is not supported for bulk import statements.");
}
}
else if (col.Type.HasValue)
diff --git a/src/Umbraco.Infrastructure/Persistence/SqlSyntax/ISqlSyntaxProvider.cs b/src/Umbraco.Infrastructure/Persistence/SqlSyntax/ISqlSyntaxProvider.cs
index 6c551648b7..75d348df1a 100644
--- a/src/Umbraco.Infrastructure/Persistence/SqlSyntax/ISqlSyntaxProvider.cs
+++ b/src/Umbraco.Infrastructure/Persistence/SqlSyntax/ISqlSyntaxProvider.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Data;
using System.Text.RegularExpressions;
@@ -28,7 +28,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.SqlSyntax
string GetQuotedName(string name);
bool DoesTableExist(IDatabase db, string tableName);
string GetIndexType(IndexTypes indexTypes);
- string GetSpecialDbType(SpecialDbTypes dbTypes);
+ string GetSpecialDbType(SpecialDbType dbType);
string CreateTable { get; }
string DropTable { get; }
string AddColumn { get; }
diff --git a/src/Umbraco.Infrastructure/Persistence/SqlSyntax/SqlSyntaxProviderBase.cs b/src/Umbraco.Infrastructure/Persistence/SqlSyntax/SqlSyntaxProviderBase.cs
index 24548fd36b..20cbb689c1 100644
--- a/src/Umbraco.Infrastructure/Persistence/SqlSyntax/SqlSyntaxProviderBase.cs
+++ b/src/Umbraco.Infrastructure/Persistence/SqlSyntax/SqlSyntaxProviderBase.cs
@@ -54,38 +54,36 @@ namespace Umbraco.Cms.Infrastructure.Persistence.SqlSyntax
public Regex AliasRegex { get; }
- public string GetWildcardPlaceholder()
- {
- return "%";
- }
+ public string GetWildcardPlaceholder() => "%";
- public string StringLengthNonUnicodeColumnDefinitionFormat = "VARCHAR({0})";
- public string StringLengthUnicodeColumnDefinitionFormat = "NVARCHAR({0})";
- public string DecimalColumnDefinitionFormat = "DECIMAL({0},{1})";
+ public string StringLengthNonUnicodeColumnDefinitionFormat { get; } = "VARCHAR({0})";
+ public string StringLengthUnicodeColumnDefinitionFormat { get; } = "NVARCHAR({0})";
+ public string DecimalColumnDefinitionFormat { get; } = "DECIMAL({0},{1})";
- public string DefaultValueFormat = "DEFAULT ({0})";
- public int DefaultStringLength = 255;
- public int DefaultDecimalPrecision = 20;
- public int DefaultDecimalScale = 9;
+ public string DefaultValueFormat { get; } = "DEFAULT ({0})";
+ public int DefaultStringLength { get; } = 255;
+ public int DefaultDecimalPrecision { get; } = 20;
+ public int DefaultDecimalScale { get; } = 9;
//Set by Constructor
- public string StringColumnDefinition;
- public string StringLengthColumnDefinitionFormat;
+ public string StringColumnDefinition { get; }
+ public string StringLengthColumnDefinitionFormat { get; }
- 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;
- public string BlobColumnDefinition = "BLOB";
- public string DateTimeColumnDefinition = "DATETIME";
- public string TimeColumnDefinition = "DATETIME";
+ public string AutoIncrementDefinition { get; protected set; } = "AUTOINCREMENT";
+ public string IntColumnDefinition { get; } = "INTEGER";
+ public string LongColumnDefinition { get; } = "BIGINT";
+ public string GuidColumnDefinition { get; protected set; } = "GUID";
+ public string BoolColumnDefinition { get; protected set; } = "BOOL";
+ public string RealColumnDefinition { get; protected set; } = "DOUBLE";
+ public string DecimalColumnDefinition { get; protected set; }
+ public string BlobColumnDefinition { get; protected set; } = "BLOB";
+ public string DateTimeColumnDefinition { get; } = "DATETIME";
+ public string TimeColumnDefinition { get; protected set; } = "DATETIME";
protected IList> ClauseOrder { get; }
- protected DbTypes DbTypeMap = new DbTypes();
+ protected DbTypes DbTypeMap { get; } = new DbTypes();
+
protected void InitColumnTypeMap()
{
DbTypeMap.Set(DbType.String, StringColumnDefinition);
@@ -100,8 +98,8 @@ namespace Umbraco.Cms.Infrastructure.Persistence.SqlSyntax
DbTypeMap.Set(DbType.DateTime, DateTimeColumnDefinition);
DbTypeMap.Set(DbType.Time, TimeColumnDefinition);
DbTypeMap.Set(DbType.Time, TimeColumnDefinition);
- DbTypeMap.Set(DbType.Time, TimeColumnDefinition);
- DbTypeMap.Set(DbType.Time, TimeColumnDefinition);
+ DbTypeMap.Set(DbType.DateTimeOffset, TimeColumnDefinition);
+ DbTypeMap.Set(DbType.DateTimeOffset, TimeColumnDefinition);
DbTypeMap.Set(DbType.Byte, IntColumnDefinition);
DbTypeMap.Set(DbType.Byte, IntColumnDefinition);
@@ -193,17 +191,17 @@ namespace Umbraco.Cms.Infrastructure.Persistence.SqlSyntax
return indexType;
}
- public virtual string GetSpecialDbType(SpecialDbTypes dbTypes)
+ public virtual string GetSpecialDbType(SpecialDbType dbType)
{
- if (dbTypes == SpecialDbTypes.NCHAR)
+ if (dbType == SpecialDbType.NCHAR)
{
- return "NCHAR";
+ return SpecialDbType.NCHAR;
}
- else if (dbTypes == SpecialDbTypes.NTEXT)
+ else if (dbType == SpecialDbType.NTEXT)
{
- return "NTEXT";
+ return SpecialDbType.NTEXT;
}
- else if (dbTypes == SpecialDbTypes.NVARCHARMAX)
+ else if (dbType == SpecialDbType.NVARCHARMAX)
{
return "NVARCHAR(MAX)";
}
@@ -470,14 +468,14 @@ namespace Umbraco.Cms.Infrastructure.Persistence.SqlSyntax
if (column.Type.HasValue == false && string.IsNullOrEmpty(column.CustomType) == false)
return column.CustomType;
- if (column.HasSpecialDbType)
+ if (column.CustomDbType.HasValue)
{
- if (column.Size != default(int))
+ if (column.Size != default)
{
- return $"{GetSpecialDbType(column.DbType)}({column.Size})";
+ return $"{GetSpecialDbType(column.CustomDbType.Value)}({column.Size})";
}
- return GetSpecialDbType(column.DbType);
+ return GetSpecialDbType(column.CustomDbType.Value);
}
var type = column.Type.HasValue
diff --git a/src/Umbraco.Persistence.SqlCe/SqlCeSyntaxProvider.cs b/src/Umbraco.Persistence.SqlCe/SqlCeSyntaxProvider.cs
index e81b6135da..274c585fa2 100644
--- a/src/Umbraco.Persistence.SqlCe/SqlCeSyntaxProvider.cs
+++ b/src/Umbraco.Persistence.SqlCe/SqlCeSyntaxProvider.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
@@ -300,10 +300,14 @@ where table_name=@0 and column_name=@1", tableName, columnName).FirstOrDefault()
GetQuotedTableName(index.TableName), columns);
}
- public override string GetSpecialDbType(SpecialDbTypes dbTypes)
+ public override string GetSpecialDbType(SpecialDbType dbTypes)
{
- if (dbTypes == SpecialDbTypes.NVARCHARMAX) // SqlCE does not have nvarchar(max) for now
+ // SqlCE does not have nvarchar(max) for now
+ if (dbTypes == SpecialDbType.NVARCHARMAX)
+ {
return "NTEXT";
+ }
+
return base.GetSpecialDbType(dbTypes);
}
public override SqlDbType GetSqlDbType(DbType dbType)