Fixes sql server DateTimeOffset mapping. Makes Custom DB types much more flexible and usable by 3rd parties.
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Persistence.DatabaseAnnotations
|
||||
{
|
||||
/// <summary>
|
||||
/// Allows for specifying custom DB types that are not natively mapped.
|
||||
/// </summary>
|
||||
public struct SpecialDbType : IEquatable<SpecialDbType>
|
||||
{
|
||||
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<string>.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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="SpecialDbTypes"/> for this column
|
||||
/// Gets or sets the <see cref="SpecialDbType"/> for this column
|
||||
/// </summary>
|
||||
public SpecialDbTypes DatabaseType { get; private set; }
|
||||
public SpecialDbType DatabaseType { get; private set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
namespace Umbraco.Cms.Infrastructure.Persistence.DatabaseAnnotations
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public enum SpecialDbTypes
|
||||
{
|
||||
NTEXT,
|
||||
NCHAR,
|
||||
NVARCHARMAX
|
||||
NVARCHARMAX,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
|
||||
/// <summary>
|
||||
/// Used for column types that cannot be natively mapped.
|
||||
/// </summary>
|
||||
public SpecialDbType? CustomDbType { get; set; }
|
||||
|
||||
public virtual int Seeding { get; set; }
|
||||
public virtual int Size { get; set; }
|
||||
public virtual int Precision { get; set; }
|
||||
|
||||
@@ -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<SpecialDbTypeAttribute>();
|
||||
if (databaseTypeAttribute != null)
|
||||
{
|
||||
definition.HasSpecialDbType = true;
|
||||
definition.DbType = databaseTypeAttribute.DatabaseType;
|
||||
definition.CustomDbType = databaseTypeAttribute.DatabaseType;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -24,15 +24,16 @@ namespace Umbraco.Cms.Infrastructure.Persistence
|
||||
IEnumerable<IProviderSpecificMapperFactory> 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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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<Func<ColumnDefinition, string>> ClauseOrder { get; }
|
||||
|
||||
protected DbTypes DbTypeMap = new DbTypes();
|
||||
protected DbTypes DbTypeMap { get; } = new DbTypes();
|
||||
|
||||
protected void InitColumnTypeMap()
|
||||
{
|
||||
DbTypeMap.Set<string>(DbType.String, StringColumnDefinition);
|
||||
@@ -100,8 +98,8 @@ namespace Umbraco.Cms.Infrastructure.Persistence.SqlSyntax
|
||||
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<DateTimeOffset>(DbType.DateTimeOffset, TimeColumnDefinition);
|
||||
DbTypeMap.Set<DateTimeOffset?>(DbType.DateTimeOffset, TimeColumnDefinition);
|
||||
|
||||
DbTypeMap.Set<byte>(DbType.Byte, IntColumnDefinition);
|
||||
DbTypeMap.Set<byte?>(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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user