Migrate PropertyData table

This commit is contained in:
Stephan
2017-11-01 10:42:46 +01:00
parent 472cb41190
commit e5b22bf731
52 changed files with 598 additions and 268 deletions

View File

@@ -5,56 +5,57 @@ using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Models.Rdbms
{
[TableName(Constants.DatabaseSchema.Tables.Node)]
[TableName(TableName)]
[PrimaryKey("id")]
[ExplicitColumns]
internal class NodeDto
{
private const string TableName = Constants.DatabaseSchema.Tables.Node;
public const int NodeIdSeed = 1060;
[Column("id")]
[PrimaryKeyColumn(Name = "PK_structure", IdentitySeed = NodeIdSeed)]
[PrimaryKeyColumn(Name = "PK_" + TableName, IdentitySeed = NodeIdSeed)]
public int NodeId { get; set; }
[Column("trashed")]
[Constraint(Default = "0")]
[Index(IndexTypes.NonClustered, Name = "IX_umbracoNodeTrashed")]
public bool Trashed { get; set; }
[Column("uniqueId")]
[NullSetting(NullSetting = NullSettings.NotNull)]
[Index(IndexTypes.UniqueNonClustered, Name = "IX_" + TableName + "_UniqueId")]
[Constraint(Default = SystemMethods.NewGuid)]
public Guid UniqueId { get; set; }
[Column("parentID")]
[Column("parentId")]
[ForeignKey(typeof(NodeDto))]
[Index(IndexTypes.NonClustered, Name = "IX_umbracoNodeParentId")]
[Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_ParentId")]
public int ParentId { get; set; }
[Column("nodeUser")]
[NullSetting(NullSetting = NullSettings.Null)]
public int? UserId { get; set; }
[Column("level")]
public short Level { get; set; }
[Column("path")]
[Length(150)]
[Index(IndexTypes.NonClustered, Name = "IX_umbracoNodePath")]
[Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_Path")]
public string Path { get; set; }
[Column("sortOrder")]
public int SortOrder { get; set; }
[Column("uniqueID")]
[NullSetting(NullSetting = NullSettings.NotNull)]
[Index(IndexTypes.UniqueNonClustered, Name = "IX_umbracoNodeUniqueID")]
[Constraint(Default = SystemMethods.NewGuid)]
public Guid UniqueId { get; set; }
[Column("trashed")]
[Constraint(Default = "0")]
[Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_Trashed")]
public bool Trashed { get; set; }
[Column("nodeUser")] // fixme dbfix rename userId
[NullSetting(NullSetting = NullSettings.Null)]
public int? UserId { get; set; }
[Column("text")]
[NullSetting(NullSetting = NullSettings.Null)]
public string Text { get; set; }
[Column("nodeObjectType")]
[Column("nodeObjectType")] // fixme dbfix rename objectType
[NullSetting(NullSetting = NullSettings.Null)]
[Index(IndexTypes.NonClustered, Name = "IX_umbracoNodeObjectType")]
public Guid? NodeObjectType { get; set; }
[Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_ObjectType")]
public Guid? NodeObjectType { get; set; } // fixme dbfix rename ObjectType
[Column("createDate")]
[Constraint(Default = SystemMethods.CurrentDateTime)]

View File

@@ -4,91 +4,97 @@ using Umbraco.Core.Persistence.DatabaseAnnotations;
namespace Umbraco.Core.Models.Rdbms
{
[TableName(Constants.DatabaseSchema.Tables.PropertyData)]
[TableName(TableName)]
[PrimaryKey("id")]
[ExplicitColumns]
internal class PropertyDataDto
{
private const string TableName = Constants.DatabaseSchema.Tables.PropertyData;
public const int VarcharLength = 512;
public const int SegmentLength = 256;
private decimal? _decimalValue;
[Column("id")]
[PrimaryKeyColumn]
public int Id { get; set; }
[Column("contentNodeId")]
[Column("nodeId")]
[ForeignKey(typeof(NodeDto))]
[Index(IndexTypes.UniqueNonClustered, Name = "IX_cmsPropertyData_1", ForColumns = "contentNodeId,versionId,propertytypeid")]
[Index(IndexTypes.UniqueNonClustered, Name = "IX_" + TableName + "_NodeId", ForColumns = "nodeId,versionId,propertyTypeId")]
public int NodeId { get; set; }
[Column("versionId")]
[NullSetting(NullSetting = NullSettings.Null)]
[Index(IndexTypes.NonClustered, Name = "IX_cmsPropertyData_2")]
[Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_VersionId")]
public Guid? VersionId { get; set; }
[Column("propertytypeid")]
[Column("propertyTypeId")]
[ForeignKey(typeof(PropertyTypeDto))]
[Index(IndexTypes.NonClustered, Name = "IX_cmsPropertyData_3")]
[Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_PropertyTypeId")]
public int PropertyTypeId { get; set; }
[Column("dataInt")]
[Column("languageId")]
[ForeignKey(typeof(LanguageDto))]
[Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_LanguageId")]
[NullSetting(NullSetting = NullSettings.Null)]
public int? Integer { get; set; }
public int LanguageId { get; set; }
private decimal? _decimalValue;
[Column("dataDecimal")]
[Column("segment")]
[Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_Segment")]
[NullSetting(NullSetting = NullSettings.Null)]
public decimal? Decimal
[Length(SegmentLength)]
public string Segment { get; set; }
[Column("intValue")]
[NullSetting(NullSetting = NullSettings.Null)]
public int? IntegerValue { get; set; }
[Column("decimalValue")]
[NullSetting(NullSetting = NullSettings.Null)]
public decimal? DecimalValue
{
get => _decimalValue;
set => _decimalValue = value?.Normalize();
}
[Column("dataDate")]
[Column("dateValue")]
[NullSetting(NullSetting = NullSettings.Null)]
public DateTime? Date { get; set; }
public DateTime? DateValue { get; set; }
[Column("dataNvarchar")]
[Column("varcharValue")]
[NullSetting(NullSetting = NullSettings.Null)]
[Length(500)]
public string VarChar { get; set; }
[Length(VarcharLength)]
public string VarcharValue { get; set; }
[Column("dataNtext")]
[Column("textValue")]
[NullSetting(NullSetting = NullSettings.Null)]
[SpecialDbType(SpecialDbTypes.NTEXT)]
public string Text { get; set; }
public string TextValue { get; set; }
[ResultColumn]
[Reference(ReferenceType.OneToOne, ColumnName = "PropertyTypeId")]
public PropertyTypeDto PropertyTypeDto { get; set; }
[Ignore]
public object GetValue
public object Value
{
get
{
if (Integer.HasValue)
{
return Integer.Value;
}
if (IntegerValue.HasValue)
return IntegerValue.Value;
if (Decimal.HasValue)
{
return Decimal.Value;
}
if (DecimalValue.HasValue)
return DecimalValue.Value;
if (Date.HasValue)
{
return Date.Value;
}
if (DateValue.HasValue)
return DateValue.Value;
if (string.IsNullOrEmpty(VarChar) == false)
{
return VarChar;
}
if (!string.IsNullOrEmpty(VarcharValue))
return VarcharValue;
if (string.IsNullOrEmpty(Text) == false)
{
return Text;
}
if (!string.IsNullOrEmpty(TextValue))
return TextValue;
return null;
}
@@ -103,12 +109,13 @@ namespace Umbraco.Core.Models.Rdbms
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
if (obj.GetType() != GetType()) return false;
return Equals((PropertyDataDto) obj);
}
public override int GetHashCode()
{
// ReSharper disable once NonReadonlyMemberInGetHashCode
return Id;
}
}

View File

@@ -15,19 +15,19 @@ namespace Umbraco.Core
public const string Node = /*TableNamePrefix*/ "umbraco" + "Node";
public const string NodeData = /*TableNamePrefix*/ "cms" + "ContentNu";
public const string NodeXml = /*TableNamePrefix*/ "cms" + "ContentXml";
public const string NodePreviewXml = /*TableNamePrefix*/ "cms" + "PreviewXml"; // fixme kill merge with ContentXml
public const string NodePreviewXml = /*TableNamePrefix*/ "cms" + "PreviewXml"; // fixme dbfix kill merge with ContentXml
public const string ContentType = /*TableNamePrefix*/ "cms" + "ContentType"; // fixme rename and split uElementType, uDocumentType
public const string ContentType = /*TableNamePrefix*/ "cms" + "ContentType"; // fixme dbfixrename and split uElementType, uDocumentType
public const string ContentChildType = /*TableNamePrefix*/ "cms" + "ContentTypeAllowedContentType";
public const string DocumentType = /*TableNamePrefix*/ "cms" + "DocumentType"; // fixme must rename corresponding DTO
public const string ElementTypeTree = /*TableNamePrefix*/ "cms" + "ContentType2ContentType"; // fixme why can't we just use uNode for this?
public const string DocumentType = /*TableNamePrefix*/ "cms" + "DocumentType"; // fixme dbfixmust rename corresponding DTO
public const string ElementTypeTree = /*TableNamePrefix*/ "cms" + "ContentType2ContentType"; // fixme dbfixwhy can't we just use uNode for this?
public const string DataType = /*TableNamePrefix*/ "cms" + "DataType";
public const string DataTypePreValue = /*TableNamePrefix*/ "cms" + "DataTypePreValues"; // fixme kill merge with uDataType
public const string DataTypePreValue = /*TableNamePrefix*/ "cms" + "DataTypePreValues"; // fixme dbfixkill merge with uDataType
public const string Template = /*TableNamePrefix*/ "cms" + "Template";
public const string Content = /*TableNamePrefix*/ "cms" + "Content"; // fixme merge into uDocument
public const string ContentVersion = /*TableNamePrefix*/ "cms" + "ContentVersion"; // fixme rename uDocumentVersion
public const string Document = /*TableNamePrefix*/ "cms" + "Document"; // fixme merge with others + no more version here
public const string Content = /*TableNamePrefix*/ "cms" + "Content"; // fixme dbfix merge into uDocument
public const string ContentVersion = /*TableNamePrefix*/ "cms" + "ContentVersion"; // fixme dbfix rename uDocumentVersion
public const string Document = /*TableNamePrefix*/ "cms" + "Document"; // fixme dbfix merge with others + no more version here
public const string PropertyType = /*TableNamePrefix*/ "cms" + "PropertyType";
public const string PropertyTypeGroup = /*TableNamePrefix*/ "cms" + "PropertyTypeGroup";

View File

@@ -39,7 +39,7 @@ namespace Umbraco.Core.Persistence.Factories
var propertyDataDto = dtos.LastOrDefault(x => x.PropertyTypeId == propertyType.Id);
var property = propertyDataDto == null
? propertyType.CreatePropertyFromValue(null)
: propertyType.CreatePropertyFromRawValue(propertyDataDto.GetValue,
: propertyType.CreatePropertyFromRawValue(propertyDataDto.Value,
propertyDataDto.VersionId.Value,
propertyDataDto.Id);
try
@@ -87,7 +87,7 @@ namespace Umbraco.Core.Persistence.Factories
{
if (property.Value is bool || property.PropertyType.PropertyEditorAlias == Constants.PropertyEditors.TrueFalseAlias)
{
dto.Integer = property.Value != null && string.IsNullOrEmpty(property.Value.ToString())
dto.IntegerValue = property.Value != null && string.IsNullOrEmpty(property.Value.ToString())
? 0
: Convert.ToInt32(property.Value);
}
@@ -96,7 +96,7 @@ namespace Umbraco.Core.Persistence.Factories
int val;
if ((property.Value != null && string.IsNullOrWhiteSpace(property.Value.ToString()) == false) && int.TryParse(property.Value.ToString(), out val))
{
dto.Integer = val;
dto.IntegerValue = val;
}
}
}
@@ -105,7 +105,7 @@ namespace Umbraco.Core.Persistence.Factories
decimal val;
if (decimal.TryParse(property.Value.ToString(), out val))
{
dto.Decimal = val; // property value should be normalized already
dto.DecimalValue = val; // property value should be normalized already
}
}
else if (property.DataTypeDatabaseType == DataTypeDatabaseType.Date && property.Value != null && string.IsNullOrWhiteSpace(property.Value.ToString()) == false)
@@ -113,16 +113,16 @@ namespace Umbraco.Core.Persistence.Factories
DateTime date;
if (DateTime.TryParse(property.Value.ToString(), out date))
{
dto.Date = date;
dto.DateValue = date;
}
}
else if (property.DataTypeDatabaseType == DataTypeDatabaseType.Ntext && property.Value != null)
{
dto.Text = property.Value.ToString();
dto.TextValue = property.Value.ToString();
}
else if (property.DataTypeDatabaseType == DataTypeDatabaseType.Nvarchar && property.Value != null)
{
dto.VarChar = property.Value.ToString();
dto.VarcharValue = property.Value.ToString();
}
propertyDataDtos.Add(dto);

View File

@@ -38,22 +38,22 @@ namespace Umbraco.Core.Persistence.Mappers
CacheMap<Member, MemberDto>(src => src.Username, dto => dto.LoginName);
CacheMap<Member, MemberDto>(src => src.RawPasswordValue, dto => dto.Password);
CacheMap<Member, PropertyDataDto>(src => src.IsApproved, dto => dto.Integer);
CacheMap<Member, PropertyDataDto>(src => src.IsLockedOut, dto => dto.Integer);
CacheMap<Member, PropertyDataDto>(src => src.Comments, dto => dto.Text);
CacheMap<Member, PropertyDataDto>(src => src.RawPasswordAnswerValue, dto => dto.VarChar);
CacheMap<Member, PropertyDataDto>(src => src.PasswordQuestion, dto => dto.VarChar);
CacheMap<Member, PropertyDataDto>(src => src.FailedPasswordAttempts, dto => dto.Integer);
CacheMap<Member, PropertyDataDto>(src => src.LastLockoutDate, dto => dto.Date);
CacheMap<Member, PropertyDataDto>(src => src.LastLoginDate, dto => dto.Date);
CacheMap<Member, PropertyDataDto>(src => src.LastPasswordChangeDate, dto => dto.Date);
CacheMap<Member, PropertyDataDto>(src => src.IsApproved, dto => dto.IntegerValue);
CacheMap<Member, PropertyDataDto>(src => src.IsLockedOut, dto => dto.IntegerValue);
CacheMap<Member, PropertyDataDto>(src => src.Comments, dto => dto.TextValue);
CacheMap<Member, PropertyDataDto>(src => src.RawPasswordAnswerValue, dto => dto.VarcharValue);
CacheMap<Member, PropertyDataDto>(src => src.PasswordQuestion, dto => dto.VarcharValue);
CacheMap<Member, PropertyDataDto>(src => src.FailedPasswordAttempts, dto => dto.IntegerValue);
CacheMap<Member, PropertyDataDto>(src => src.LastLockoutDate, dto => dto.DateValue);
CacheMap<Member, PropertyDataDto>(src => src.LastLoginDate, dto => dto.DateValue);
CacheMap<Member, PropertyDataDto>(src => src.LastPasswordChangeDate, dto => dto.DateValue);
/* Internal experiment */
CacheMap<Member, PropertyDataDto>(src => src.DateTimePropertyValue, dto => dto.Date);
CacheMap<Member, PropertyDataDto>(src => src.IntegerPropertyValue, dto => dto.Integer);
CacheMap<Member, PropertyDataDto>(src => src.BoolPropertyValue, dto => dto.Integer);
CacheMap<Member, PropertyDataDto>(src => src.LongStringPropertyValue, dto => dto.Text);
CacheMap<Member, PropertyDataDto>(src => src.ShortStringPropertyValue, dto => dto.VarChar);
CacheMap<Member, PropertyDataDto>(src => src.DateTimePropertyValue, dto => dto.DateValue);
CacheMap<Member, PropertyDataDto>(src => src.IntegerPropertyValue, dto => dto.IntegerValue);
CacheMap<Member, PropertyDataDto>(src => src.BoolPropertyValue, dto => dto.IntegerValue);
CacheMap<Member, PropertyDataDto>(src => src.LongStringPropertyValue, dto => dto.TextValue);
CacheMap<Member, PropertyDataDto>(src => src.ShortStringPropertyValue, dto => dto.VarcharValue);
CacheMap<Member, PropertyTypeDto>(src => src.PropertyTypeAlias, dto => dto.Alias);
}
}

View File

@@ -1,12 +1,10 @@
using NPoco;
namespace Umbraco.Core.Persistence.Migrations
namespace Umbraco.Core.Persistence.Migrations
{
/// <summary>
/// Marker interface for migration expressions
/// </summary>
public interface IMigrationExpression
{
string Process(IUmbracoDatabase database);
string Process(IMigrationContext context);
}
}

View File

@@ -35,7 +35,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
#region All Ordered Tables
private static readonly Dictionary<int, Type> OrderedTables = new Dictionary<int, Type>
public static readonly Dictionary<int, Type> OrderedTables = new Dictionary<int, Type>
{
{0, typeof (NodeDto)},
{1, typeof (ContentTypeDto)},

View File

@@ -28,7 +28,7 @@ namespace Umbraco.Core.Persistence.Migrations
public string GetSql()
{
var sb = new StringBuilder();
foreach (var sql in Expressions.Select(x => x.Process(Database)))
foreach (var sql in Expressions.Select(x => x.Process(this)))
{
sb.Append(sql);
sb.AppendLine();

View File

@@ -36,7 +36,7 @@ namespace Umbraco.Core.Persistence.Migrations
|| SupportedDatabaseTypes.Any(x => CurrentDatabaseType.GetType().Inherits(x.GetType()));
}
public virtual string Process(IUmbracoDatabase database)
public virtual string Process(IMigrationContext context)
{
return ToString();
}

View File

@@ -186,7 +186,7 @@ namespace Umbraco.Core.Persistence.Migrations
int i = 1;
foreach (var expression in context.Expressions)
{
var sql = expression.Process(context.Database);
var sql = expression.Process(context);
if (string.IsNullOrEmpty(sql))
{
i++;
@@ -211,6 +211,7 @@ namespace Umbraco.Core.Persistence.Migrations
//Execute the SQL up to the point of a GO statement
var exeSql = sb.ToString();
_logger.Info<MigrationRunner>("Executing sql statement " + i + ": " + exeSql);
Console.WriteLine("EXEC: " + exeSql);
context.Database.Execute(exeSql);
//restart the string builder
@@ -226,6 +227,7 @@ namespace Umbraco.Core.Persistence.Migrations
{
var exeSql = sb.ToString();
_logger.Info<MigrationRunner>("Executing sql statement " + i + ": " + exeSql);
Console.WriteLine("EXEC: " + exeSql);
context.Database.Execute(exeSql);
}
}

View File

@@ -38,6 +38,28 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create
AddSql(sql);
}
public void KeysAndIndexes<T>()
{
var tableDefinition = DefinitionFactory.GetTableDefinition(typeof(T), SqlSyntax);
AddSql(SqlSyntax.FormatPrimaryKey(tableDefinition));
foreach (var sql in SqlSyntax.Format(tableDefinition.ForeignKeys))
AddSql(sql);
foreach (var sql in SqlSyntax.Format(tableDefinition.Indexes))
AddSql(sql);
}
public void KeysAndIndexes(Type typeOfDto)
{
var tableDefinition = DefinitionFactory.GetTableDefinition(typeOfDto, SqlSyntax);
AddSql(SqlSyntax.FormatPrimaryKey(tableDefinition));
foreach (var sql in SqlSyntax.Format(tableDefinition.ForeignKeys))
AddSql(sql);
foreach (var sql in SqlSyntax.Format(tableDefinition.Indexes))
AddSql(sql);
}
private void AddSql(string sql)
{
var expression = new ExecuteSqlStatementExpression(_context, _supportedDatabaseTypes) { SqlStatement = sql };

View File

@@ -1,4 +1,5 @@
using Umbraco.Core.Persistence.Migrations.Syntax.Create.Column;
using System;
using Umbraco.Core.Persistence.Migrations.Syntax.Create.Column;
using Umbraco.Core.Persistence.Migrations.Syntax.Create.Constraint;
using Umbraco.Core.Persistence.Migrations.Syntax.Create.ForeignKey;
using Umbraco.Core.Persistence.Migrations.Syntax.Create.Index;
@@ -9,6 +10,8 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create
public interface ICreateBuilder : IFluentSyntax
{
void Table<T>();
void KeysAndIndexes<T>();
void KeysAndIndexes(Type typeOfDto);
ICreateTableWithColumnSyntax Table(string tableName);
ICreateColumnOnTableSyntax Column(string columnName);

View File

@@ -1,4 +1,5 @@
using NPoco;
using System;
using NPoco;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.Migrations.Syntax.Delete.Column;
using Umbraco.Core.Persistence.Migrations.Syntax.Delete.Constraint;

View File

@@ -22,7 +22,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Execute
_context.Expressions.Add(expression);
}
public void Code(Func<IUmbracoDatabase, string> codeStatement)
public void Code(Func<IMigrationContext, string> codeStatement)
{
var expression = new ExecuteCodeStatementExpression(_context, _supportedDatabaseTypes) { CodeStatement = codeStatement };
_context.Expressions.Add(expression);

View File

@@ -0,0 +1,56 @@
using System.Linq;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Syntax.Execute
{
public static class ExecuteBuilderExtensions
{
public static void DropKeysAndIndexes(this IExecuteBuilder execute, string tableName)
{
execute.Code(context => DropKeysAndIndexes(context, tableName));
}
public static void DropKeysAndIndexes(this IExecuteBuilder execute)
{
execute.Code(DropKeysAndIndexes);
}
private static string DropKeysAndIndexes(IMigrationContext context, string tableName)
{
var local = context.GetLocalMigration();
// drop indexes
var indexes = context.SqlContext.SqlSyntax.GetDefinedIndexesDefinitions(context.Database).ToArray();
foreach (var index in indexes.Where(x => x.TableName == tableName))
local.Delete.Index(index.IndexName).OnTable(index.TableName);
// drop keys
var keys = context.SqlContext.SqlSyntax.GetConstraintsPerTable(context.Database).ToArray();
foreach (var key in keys.Where(x => x.Item1 == tableName && x.Item2.StartsWith("FK_")))
local.Delete.ForeignKey(key.Item2).OnTable(key.Item1);
foreach (var key in keys.Where(x => x.Item1 == tableName && x.Item2.StartsWith("PK_")))
local.Delete.PrimaryKey(key.Item2).FromTable(key.Item1);
return local.GetSql();
}
private static string DropKeysAndIndexes(IMigrationContext context)
{
var local = context.GetLocalMigration();
// drop indexes
var indexes = context.SqlContext.SqlSyntax.GetDefinedIndexesDefinitions(context.Database).ToArray();
foreach (var index in indexes)
local.Delete.Index(index.IndexName).OnTable(index.TableName);
// drop keys
var keys = context.SqlContext.SqlSyntax.GetConstraintsPerTable(context.Database).ToArray();
foreach (var key in keys.Where(x => x.Item2.StartsWith("FK_")))
local.Delete.ForeignKey(key.Item2).OnTable(key.Item1);
foreach (var key in keys.Where(x => x.Item2.StartsWith("PK_")))
local.Delete.PrimaryKey(key.Item2).FromTable(key.Item1);
return local.GetSql();
}
}
}

View File

@@ -9,14 +9,11 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Execute.Expressions
: base(context, supportedDatabaseTypes)
{ }
public virtual Func<IUmbracoDatabase, string> CodeStatement { get; set; }
public virtual Func<IMigrationContext, string> CodeStatement { get; set; }
public override string Process(IUmbracoDatabase database)
public override string Process(IMigrationContext context)
{
if(CodeStatement != null)
return CodeStatement(database);
return base.Process(database);
return CodeStatement != null ? CodeStatement(context) : base.Process(context);
}
}
}

View File

@@ -5,6 +5,6 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Execute
public interface IExecuteBuilder : IFluentSyntax
{
void Sql(string sqlStatement);
void Code(Func<IUmbracoDatabase, string> codeStatement);
void Code(Func<IMigrationContext, string> codeStatement);
}
}

View File

@@ -13,7 +13,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Rename.Expressions
public virtual string OldName { get; set; }
public virtual string NewName { get; set; }
public override string Process(IUmbracoDatabase database)
public override string Process(IMigrationContext context)
{
if (CurrentDatabaseType.IsMySql())
{
@@ -35,7 +35,7 @@ SELECT CONCAT(
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = '{0}' AND COLUMN_NAME = '{1}'", TableName, OldName);
var columnDefinition = database.ExecuteScalar<string>(columnDefinitionSql);
var columnDefinition = context.Database.ExecuteScalar<string>(columnDefinitionSql);
return this.ToString() + " " + columnDefinition;
}

View File

@@ -32,8 +32,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionEight
private void EnsureLockObject(int id, string name)
{
Execute.Code(db =>
Execute.Code(context =>
{
var db = context.Database;
var exists = db.Exists<LockDto>(id);
if (exists) return string.Empty;
// be safe: delete old umbracoNode lock objects if any

View File

@@ -16,8 +16,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionEight
Execute.Code(MigrationCode);
}
private string MigrationCode(IUmbracoDatabase database)
private string MigrationCode(IMigrationContext context)
{
var database = context.Database;
var umbracoRedirectUrlTableName = "umbracoRedirectUrl";
var local = Context.GetLocalMigration();

View File

@@ -0,0 +1,71 @@
using System.Linq;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.Migrations.Syntax.Execute;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionEight
{
[Migration("8.0.0", 400, Constants.System.UmbracoMigrationName)]
public class VariantsMigration : MigrationBase
{
public VariantsMigration(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
// delete keys and indexes
Execute.DropKeysAndIndexes(Constants.DatabaseSchema.Tables.PropertyData);
// fixme is this enough or shall we drop *all* keys and indexes?
MigratePropertyData();
// re-create keys and indexes
Create.KeysAndIndexes<PropertyDataDto>();
}
private void MigrateContentDocumentAndVersion()
{
// todo
// add a varyBy field that's an enum (invariant, culture, segment)
}
private void MigratePropertyData()
{
// add column propertyData.languageId
if (!ColumnExists(Constants.DatabaseSchema.Tables.PropertyData, "languageId"))
Alter.Table(Constants.DatabaseSchema.Tables.PropertyData).AddColumn("languageId").AsInt32().Nullable();
// add column propertyData.segment
if (!ColumnExists(Constants.DatabaseSchema.Tables.PropertyData, "segment"))
Alter.Table(Constants.DatabaseSchema.Tables.PropertyData).AddColumn("segment").AsString(256).Nullable();
// rename column propertyData.contentNodeId to nodeId
if (ColumnExists(Constants.DatabaseSchema.Tables.PropertyData, "contentNodeId"))
Rename.Column("contentNodeId").OnTable(Constants.DatabaseSchema.Tables.PropertyData).To("nodeId");
// rename column propertyData.dataNtext to textValue
// rename column propertyData.dataNvarchar to varcharValue
// rename column propertyData.dataDecimal to decimalValue
// rename column propertyData.dataInt to intValue
// rename column propertyData.dataDate to dateValue
if (ColumnExists(Constants.DatabaseSchema.Tables.PropertyData, "dataNtext"))
Rename.Column("dataNtext").OnTable(Constants.DatabaseSchema.Tables.PropertyData).To("textValue");
if (ColumnExists(Constants.DatabaseSchema.Tables.PropertyData, "dataNvarchar"))
Rename.Column("dataNtext").OnTable(Constants.DatabaseSchema.Tables.PropertyData).To("varcharValue");
if (ColumnExists(Constants.DatabaseSchema.Tables.PropertyData, "dataDecimal"))
Rename.Column("dataDecimal").OnTable(Constants.DatabaseSchema.Tables.PropertyData).To("decimalValue");
if (ColumnExists(Constants.DatabaseSchema.Tables.PropertyData, "dataInt"))
Rename.Column("dataInt").OnTable(Constants.DatabaseSchema.Tables.PropertyData).To("intValue");
if (ColumnExists(Constants.DatabaseSchema.Tables.PropertyData, "dataDate"))
Rename.Column("dataDate").OnTable(Constants.DatabaseSchema.Tables.PropertyData).To("dateValue");
}
private bool ColumnExists(string tableName, string columnName)
{
// that's ok even on MySql
var columns = SqlSyntax.GetColumnsInSchema(Context.Database).Distinct().ToArray();
return columns.Any(x => x.TableName.InvariantEquals(tableName) && x.ColumnName.InvariantEquals(columnName));
}
}
}

View File

@@ -30,8 +30,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
Execute.Code(UpdateRelatedLinksDataDo);
}
public string UpdateRelatedLinksDataDo(IDatabase database)
public string UpdateRelatedLinksDataDo(IMigrationContext context)
{
var database = context?.Database;
if (database != null)
{
var dtSql = Sql().Select("nodeId").From<DataTypeDto>()
@@ -45,7 +46,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
+ " WHERE propertyTypeId in (SELECT id from cmsPropertyType where dataTypeID IN (@dataTypeIds))", new { /*dataTypeIds =*/ dataTypeIds });
if (propertyData.Any() == false) return string.Empty;
var nodesIdsWithProperty = propertyData.Select(x => (int) x.contentNodeId).Distinct().ToArray();
var nodesIdsWithProperty = propertyData.Select(x => (int) x.nodeId).Distinct().ToArray();
var cmsContentXmlEntries = new List<ContentXmlDto>();
//We're doing an "IN" query here but SQL server only supports 2100 query parameters so we're going to split on that
@@ -65,25 +66,25 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
foreach (var data in propertyData)
{
if (string.IsNullOrEmpty(data.dataNtext) == false)
if (string.IsNullOrEmpty(data.textValue) == false)
{
XmlDocument xml;
//fetch the current data (that's in xml format)
try
{
xml = new XmlDocument();
xml.LoadXml(data.dataNtext);
xml.LoadXml(data.textValue);
}
catch (Exception ex)
{
int dataId = data.id;
int dataNodeId = data.contentNodeId;
string dataText = data.dataNtext;
int dataNodeId = data.nodeId;
string dataText = data.textValue;
Logger.Error<UpdateRelatedLinksData>("The data stored for property id " + dataId + " on document " + dataNodeId +
" is not valid XML, the data will be removed because it cannot be converted to the new format. The value was: " + dataText, ex);
data.dataNtext = "";
database.Update("cmsPropertyData", "id", data, new[] { "dataNText" });
data.textValue = "";
database.Update("cmsPropertyData", "id", data, new[] { "textValue" });
UpdateXmlTable(propertyTypes, data, cmsContentXmlEntries, database);
@@ -116,9 +117,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
}
//store the serialized data
data.dataNtext = JsonConvert.SerializeObject(links);
data.textValue = JsonConvert.SerializeObject(links);
database.Update("cmsPropertyData", "id", data, new[] { "dataNText" });
database.Update("cmsPropertyData", "id", data, new[] { "textValue" });
UpdateXmlTable(propertyTypes, data, cmsContentXmlEntries, database);
@@ -139,14 +140,14 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
var propertyType = propertyTypes.SingleOrDefault(x => x.Id == data.propertytypeid);
if (propertyType != null)
{
var xmlItem = cmsContentXmlEntries.SingleOrDefault(x => x.NodeId == data.contentNodeId);
var xmlItem = cmsContentXmlEntries.SingleOrDefault(x => x.NodeId == data.nodeId);
if (xmlItem != null)
{
var x = XElement.Parse(xmlItem.Xml);
var prop = x.Element(propertyType.Alias);
if (prop != null)
{
prop.ReplaceAll(new XCData(data.dataNtext));
prop.ReplaceAll(new XCData(data.textValue));
database.Update(xmlItem);
}
}

View File

@@ -22,8 +22,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFiveFiv
private void EnsureLockObject(int id, string name)
{
Execute.Code(db =>
Execute.Code(context =>
{
var db = context.Database;
var exists = db.Exists<LockDto>(id);
if (exists) return string.Empty;
// be safe: delete old umbracoNode lock objects if any

View File

@@ -23,7 +23,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFiveZer
Execute.Code(MigrationCode);
}
private string MigrationCode(IUmbracoDatabase database)
private string MigrationCode(IMigrationContext context)
{
var local = Context.GetLocalMigration();

View File

@@ -41,7 +41,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFiveZer
var delPropQry = SqlSyntax.GetDeleteSubquery(
"cmsPropertyData",
"id",
Sql("SELECT MIN(id) FROM cmsPropertyData GROUP BY contentNodeId, versionId, propertytypeid HAVING MIN(id) IS NOT NULL"),
Sql("SELECT MIN(id) FROM cmsPropertyData GROUP BY nodeId, versionId, propertytypeid HAVING MIN(id) IS NOT NULL"),
WhereInType.NotIn);
Execute.Sql(delPropQry.SQL);
}
@@ -50,13 +50,13 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFiveZer
//NOTE: Even though the above will work for MSSQL, we are not going to execute the
// nested delete sub query logic since it will be slower and there could be a ton of property
// data here so needs to be as fast as possible.
Execute.Sql("DELETE FROM cmsPropertyData WHERE id NOT IN (SELECT MIN(id) FROM cmsPropertyData GROUP BY contentNodeId, versionId, propertytypeid HAVING MIN(id) IS NOT NULL)");
Execute.Sql("DELETE FROM cmsPropertyData WHERE id NOT IN (SELECT MIN(id) FROM cmsPropertyData GROUP BY nodeId, versionId, propertytypeid HAVING MIN(id) IS NOT NULL)");
}
//we need to re create this index
Delete.Index("IX_cmsPropertyData_1").OnTable("cmsPropertyData");
Create.Index("IX_cmsPropertyData_1").OnTable("cmsPropertyData")
.OnColumn("contentNodeId").Ascending()
.OnColumn("nodeId").Ascending()
.OnColumn("versionId").Ascending()
.OnColumn("propertytypeid").Ascending()
.WithOptions().NonClustered()

View File

@@ -39,8 +39,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFourZer
}
}
private static string UpdateGuids(IDatabase database)
private static string UpdateGuids(IMigrationContext context)
{
var database = context.Database;
var updates = new List<Tuple<Guid, int>>();
foreach (var data in database.Query<dynamic>(@"

View File

@@ -13,8 +13,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSevenZe
public override void Up()
{
Execute.Code(database =>
Execute.Code(context =>
{
var database = context.Database;
//Now we need to check if we can actually do this because we won't be able to if there's data in there that is too long
var colLen = (SqlSyntax is MySqlSyntaxProvider)
? database.ExecuteScalar<int?>(string.Format("select max(LENGTH({0})) from cmsDictionary", SqlSyntax.GetQuotedColumnName("key")))

View File

@@ -16,8 +16,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSevenZe
public override void Up()
{
Execute.Code(database =>
Execute.Code(context =>
{
var database = context.Database;
var userGroups = database.Fetch<UserGroupDto>(
Context.SqlContext.Sql().Select("*")
.From<UserGroupDto>()

View File

@@ -15,8 +15,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSevenZe
{
//Now we need to check if we can actually do this because we won't be able to if there's data in there that is too long
Execute.Code(database =>
Execute.Code(context =>
{
var database = context.Database;
var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(database);
var colLen = SqlSyntax is MySqlSyntaxProvider

View File

@@ -13,8 +13,10 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
public override void Up()
{
Execute.Code(database =>
Execute.Code(context =>
{
var database = context.Database;
//Now we need to check if we can actually d6 this because we won't be able to if there's data in there that is too long
//http://issues.umbraco.org/issue/U4-9758

View File

@@ -21,8 +21,10 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
{
//This will remove any corrupt/duplicate data in the relation table before the index is applied
//Ensure this executes in a defered block which will be done inside of the migration transaction
this.Execute.Code(database =>
this.Execute.Code(context =>
{
var database = context.Database;
//We need to check if this index has corrupted data and then clear that data
var duplicates = database.Fetch<dynamic>("SELECT parentId,childId,relType FROM umbracoRelation GROUP BY parentId,childId,relType HAVING COUNT(*) > 1");
if (duplicates.Count > 0)

View File

@@ -23,8 +23,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
private void EnsureLockObject(int id, string name)
{
Execute.Code(db =>
Execute.Code(context =>
{
var db = context.Database;
var exists = db.Exists<LockDto>(id);
if (exists) return string.Empty;
// be safe: delete old umbracoNode lock objects if any

View File

@@ -40,8 +40,10 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
}
}
private static string UpdateMacroGuids(IUmbracoDatabase database)
private static string UpdateMacroGuids(IMigrationContext context)
{
var database = context.Database;
var updates = database.Query<dynamic>("SELECT id, macroAlias FROM cmsMacro")
.Select(macro => Tuple.Create((int) macro.id, ("macro____" + (string) macro.macroAlias).ToGuid()))
.ToList();
@@ -52,8 +54,10 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
return string.Empty;
}
private static string UpdateMacroPropertyGuids(IUmbracoDatabase database)
private static string UpdateMacroPropertyGuids(IMigrationContext context)
{
var database = context.Database;
var updates = database.Query<dynamic>(@"SELECT cmsMacroProperty.id id, macroPropertyAlias propertyAlias, cmsMacro.macroAlias macroAlias
FROM cmsMacroProperty
JOIN cmsMacro ON cmsMacroProperty.macro=cmsMacro.id")

View File

@@ -28,8 +28,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
}
}
private static string UpdateRelationTypeGuids(IUmbracoDatabase database)
private static string UpdateRelationTypeGuids(IMigrationContext context)
{
var database = context.Database;
var updates = database.Query<dynamic>("SELECT id, alias, name FROM umbracoRelationType")
.Select(relationType => Tuple.Create((int) relationType.id, ("relationType____" + (string) relationType.alias + "____" + (string) relationType.name).ToGuid()))
.ToList();

View File

@@ -16,8 +16,10 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
Execute.Code(UpdateTemplateGuids);
}
private static string UpdateTemplateGuids(IUmbracoDatabase database)
private static string UpdateTemplateGuids(IMigrationContext context)
{
var database = context.Database;
// we need this migration because ppl running pre-7.6 on Cloud and Courier have templates in different
// environments having different GUIDs (Courier does not sync template GUIDs) and we need to normalize
// these GUIDs so templates with the same alias on different environments have the same GUID.

View File

@@ -17,8 +17,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
//Now we need to check if we can actually d6 this because we won't be able to if there's data in there that is too long
//http://issues.umbraco.org/issue/U4-9758
Execute.Code(database =>
Execute.Code(context =>
{
var database = context.Database;
var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(database);
var colLen = (SqlSyntax is MySqlSyntaxProvider)

View File

@@ -29,8 +29,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeTw
return string.Empty;
});
Delete.FromTable("umbracoMigration").AllRows();
Execute.Code(database =>
Execute.Code(context =>
{
var database = context.Database;
if (migrations != null)
{
foreach (var migration in migrations)

View File

@@ -54,8 +54,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
//FROM umbracoNode t1
//INNER JOIN cmsTemplate t2
//ON t1.id = t2.nodeId");
Execute.Code(database =>
Execute.Code(context =>
{
var database = context.Database;
var templateData = database.Fetch<dynamic>("SELECT * FROM cmsTemplate");
foreach (var template in templateData)
@@ -72,8 +73,10 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
});
//Now we can update the path, but this needs to be done in a delegate callback so that the query runs after the updates just completed
Execute.Code(database =>
Execute.Code(context =>
{
var database = context.Database;
//NOTE: we are using dynamic because we need to get the data in a column that no longer exists in the schema
var templates = database.Fetch<dynamic>(Sql().SelectAll().From<TemplateDto>());
foreach (var template in templates)

View File

@@ -35,7 +35,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwoZero
Delete.FromTable("cmsTagRelationship").Row(new { nodeId = orphanedId });
Delete.FromTable("umbracoDomains").Row(new { domainRootStructureID = orphanedId });
Delete.FromTable("cmsDocument").Row(new { nodeId = orphanedId });
Delete.FromTable("cmsPropertyData").Row(new { contentNodeId = orphanedId });
Delete.FromTable("cmsPropertyData").Row(new { nodeId = orphanedId });
Delete.FromTable("cmsMember2MemberGroup").Row(new { Member = orphanedId });
Delete.FromTable("cmsMember").Row(new { nodeId = orphanedId });
Delete.FromTable("cmsPreviewXml").Row(new { nodeId = orphanedId });

View File

@@ -194,7 +194,7 @@ namespace Umbraco.Core.Persistence.Repositories
"DELETE FROM cmsTagRelationship WHERE nodeId = @Id",
"DELETE FROM umbracoDomains WHERE domainRootStructureID = @Id",
"DELETE FROM cmsDocument WHERE nodeId = @Id",
"DELETE FROM cmsPropertyData WHERE contentNodeId = @Id",
"DELETE FROM cmsPropertyData WHERE nodeId = @Id",
"DELETE FROM cmsPreviewXml WHERE nodeId = @Id",
"DELETE FROM cmsContentVersion WHERE ContentId = @Id",
"DELETE FROM cmsContentXml WHERE nodeId = @Id",
@@ -274,7 +274,7 @@ namespace Umbraco.Core.Persistence.Repositories
// raise event first else potential FK issues
OnUowRemovingVersion(new UnitOfWorkVersionEventArgs(UnitOfWork, id, versionId));
Database.Delete<PropertyDataDto>("WHERE contentNodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId });
Database.Delete<PropertyDataDto>("WHERE nodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId });
Database.Delete<ContentVersionDto>("WHERE ContentId = @Id AND VersionId = @VersionId", new { Id = id, VersionId = versionId });
Database.Delete<DocumentDto>("WHERE nodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId });
}

View File

@@ -71,8 +71,8 @@ namespace Umbraco.Core.Persistence.Repositories
foreach (var idGroup in ids)
{
var propSql = GetPropertySql(Constants.ObjectTypes.Media)
.Where("contentNodeId IN (@ids)", new { ids = idGroup })
.OrderBy("contentNodeId");
.Where("nodeId IN (@ids)", new { ids = idGroup })
.OrderBy("nodeId");
//This does NOT fetch all data into memory in a list, this will read
// over the records as a data reader, this is much better for performance and memory,
@@ -94,7 +94,7 @@ namespace Umbraco.Core.Persistence.Repositories
// use the available enumerator.Current if any else move to next
while (hasCurrent || propertyDataSetEnumerator.MoveNext())
{
if (propertyDataSetEnumerator.Current.contentNodeId == entity.Id)
if (propertyDataSetEnumerator.Current.nodeId == entity.Id)
{
hasCurrent = false; // enumerator.Current is not available
@@ -102,9 +102,9 @@ namespace Umbraco.Core.Persistence.Repositories
entity.AdditionalData[propertyDataSetEnumerator.Current.propertyTypeAlias] = new UmbracoEntity.EntityProperty
{
PropertyEditorAlias = propertyDataSetEnumerator.Current.propertyEditorAlias,
Value = StringExtensions.IsNullOrWhiteSpace(propertyDataSetEnumerator.Current.dataNtext)
? propertyDataSetEnumerator.Current.dataNvarchar
: StringExtensions.ConvertToJsonIfPossible(propertyDataSetEnumerator.Current.dataNtext)
Value = StringExtensions.IsNullOrWhiteSpace(propertyDataSetEnumerator.Current.textValue)
? propertyDataSetEnumerator.Current.varcharValue
: StringExtensions.ConvertToJsonIfPossible(propertyDataSetEnumerator.Current.textValue)
};
}
else
@@ -418,7 +418,7 @@ namespace Umbraco.Core.Persistence.Repositories
private Sql<ISqlContext> GetPropertySql(Guid nodeObjectType)
{
var sql = Sql()
.Select("contentNodeId, versionId, dataNvarchar, dataNtext, propertyEditorAlias, alias as propertyTypeAlias")
.Select("nodeId, versionId, varcharValue, textValue, propertyEditorAlias, alias as propertyTypeAlias")
.From<PropertyDataDto>()
.InnerJoin<NodeDto>()
.On<PropertyDataDto, NodeDto>(dto => dto.NodeId, dto => dto.NodeId)
@@ -433,7 +433,7 @@ namespace Umbraco.Core.Persistence.Repositories
private Sql<ISqlContext> GetFullSqlForMedia(Sql<ISqlContext> entitySql, Action<Sql<ISqlContext>> filter = null)
{
//this will add any dataNvarchar property to the output which can be added to the additional properties
//this will add any varcharValue property to the output which can be added to the additional properties
var sql = GetPropertySql(Constants.ObjectTypes.Media);
@@ -448,7 +448,7 @@ namespace Umbraco.Core.Persistence.Repositories
.Append(entitySql)
.Append(") tmpTbl LEFT JOIN (")
.Append(sql)
.Append(") as property ON id = property.contentNodeId")
.Append(") as property ON id = property.nodeId")
.OrderBy("sortOrder, id");
return wrappedSql;
@@ -661,11 +661,11 @@ namespace Umbraco.Core.Persistence.Repositories
[Column("propertyTypeAlias")]
public string PropertyAlias { get; set; }
[Column("dataNvarchar")]
public string NVarcharValue { get; set; }
[Column("varcharValue")]
public string VarcharValue { get; set; }
[Column("dataNtext")]
public string NTextValue { get; set; }
[Column("textValue")]
public string TextValue { get; set; }
}
/// <summary>
@@ -707,8 +707,8 @@ namespace Umbraco.Core.Persistence.Repositories
string pPropertyEditorAlias = a.propertyEditorAlias;
var pExists = pPropertyEditorAlias != null;
string pPropertyAlias = a.propertyTypeAlias;
string pNTextValue = a.dataNtext;
string pNVarcharValue = a.dataNvarchar;
string pTextValue = a.textValue;
string pNVarcharValue = a.varcharValue;
// Is this the same UmbracoEntity as the current one we're processing
if (Current != null && Current.Key == a.uniqueID)
@@ -719,9 +719,9 @@ namespace Umbraco.Core.Persistence.Repositories
Current.AdditionalData[pPropertyAlias] = new UmbracoEntity.EntityProperty
{
PropertyEditorAlias = pPropertyEditorAlias,
Value = pNTextValue.IsNullOrWhiteSpace()
Value = pTextValue.IsNullOrWhiteSpace()
? pNVarcharValue
: pNTextValue.ConvertToJsonIfPossible()
: pTextValue.ConvertToJsonIfPossible()
};
}
@@ -745,9 +745,9 @@ namespace Umbraco.Core.Persistence.Repositories
Current.AdditionalData[pPropertyAlias] = new UmbracoEntity.EntityProperty
{
PropertyEditorAlias = pPropertyEditorAlias,
Value = pNTextValue.IsNullOrWhiteSpace()
Value = pTextValue.IsNullOrWhiteSpace()
? pNVarcharValue
: pNTextValue.ConvertToJsonIfPossible()
: pTextValue.ConvertToJsonIfPossible()
};
}

View File

@@ -136,7 +136,7 @@ namespace Umbraco.Core.Persistence.Repositories
"DELETE FROM umbracoRelation WHERE childId = @Id",
"DELETE FROM cmsTagRelationship WHERE nodeId = @Id",
"DELETE FROM cmsDocument WHERE nodeId = @Id",
"DELETE FROM cmsPropertyData WHERE contentNodeId = @Id",
"DELETE FROM cmsPropertyData WHERE nodeId = @Id",
"DELETE FROM cmsContentVersion WHERE ContentId = @Id",
"DELETE FROM cmsContent WHERE nodeId = @Id",
"DELETE FROM umbracoNode WHERE id = @Id"
@@ -189,12 +189,12 @@ namespace Umbraco.Core.Persistence.Repositories
// If the stripped-down url returns null, we try again with the original url.
// Previously, the function would fail on e.g. "my_x_image.jpg"
var nodeId = GetMediaNodeIdByPath(Sql().Where<PropertyDataDto>(x => x.VarChar== umbracoFileValue));
if (nodeId < 0) nodeId = GetMediaNodeIdByPath(Sql().Where<PropertyDataDto>(x => x.VarChar == mediaPath));
var nodeId = GetMediaNodeIdByPath(Sql().Where<PropertyDataDto>(x => x.VarcharValue== umbracoFileValue));
if (nodeId < 0) nodeId = GetMediaNodeIdByPath(Sql().Where<PropertyDataDto>(x => x.VarcharValue == mediaPath));
// If no result so far, try getting from a json value stored in the ntext / nvarchar column
if (nodeId < 0) nodeId = GetMediaNodeIdByPath(Sql().Where("dataNtext LIKE @0", "%" + umbracoFileValue + "%"));
if (nodeId < 0) nodeId = GetMediaNodeIdByPath(Sql().Where("dataNvarchar LIKE @0", "%" + umbracoFileValue + "%"));
if (nodeId < 0) nodeId = GetMediaNodeIdByPath(Sql().Where("textValue LIKE @0", "%" + umbracoFileValue + "%"));
if (nodeId < 0) nodeId = GetMediaNodeIdByPath(Sql().Where("varcharValue LIKE @0", "%" + umbracoFileValue + "%"));
return nodeId < 0 ? null : Get(nodeId);
}
@@ -217,7 +217,7 @@ namespace Umbraco.Core.Persistence.Repositories
// raise event first else potential FK issues
OnUowRemovingVersion(new UnitOfWorkVersionEventArgs(UnitOfWork, id, versionId));
Database.Delete<PropertyDataDto>("WHERE contentNodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId });
Database.Delete<PropertyDataDto>("WHERE nodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId });
Database.Delete<ContentVersionDto>("WHERE ContentId = @Id AND VersionId = @VersionId", new { Id = id, VersionId = versionId });
}

View File

@@ -175,7 +175,7 @@ namespace Umbraco.Core.Persistence.Repositories
"DELETE FROM umbracoRelation WHERE parentId = @Id",
"DELETE FROM umbracoRelation WHERE childId = @Id",
"DELETE FROM cmsTagRelationship WHERE nodeId = @Id",
"DELETE FROM cmsPropertyData WHERE contentNodeId = @Id",
"DELETE FROM cmsPropertyData WHERE nodeId = @Id",
"DELETE FROM cmsMember2MemberGroup WHERE Member = @Id",
"DELETE FROM cmsMember WHERE nodeId = @Id",
"DELETE FROM cmsContentVersion WHERE ContentId = @Id",
@@ -450,7 +450,7 @@ namespace Umbraco.Core.Persistence.Repositories
// raise event first else potential FK issues
OnUowRemovingVersion(new UnitOfWorkVersionEventArgs(UnitOfWork, id, versionId));
Database.Delete<PropertyDataDto>("WHERE contentNodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId });
Database.Delete<PropertyDataDto>("WHERE nodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId });
Database.Delete<ContentVersionDto>("WHERE ContentId = @Id AND VersionId = @VersionId", new { Id = id, VersionId = versionId });
}

View File

@@ -322,10 +322,10 @@ namespace Umbraco.Core.Persistence.Repositories
{
// Sorting by a custom field, so set-up sub-query for ORDER BY clause to pull through value
// from most recent content version for the given order by field
var sortedInt = string.Format(SqlContext.SqlSyntax.ConvertIntegerToOrderableString, "dataInt");
var sortedDate = string.Format(SqlContext.SqlSyntax.ConvertDateToOrderableString, "dataDate");
var sortedString = "COALESCE(dataNvarchar,'')"; // assuming COALESCE is ok for all syntaxes
var sortedDecimal = string.Format(SqlContext.SqlSyntax.ConvertDecimalToOrderableString, "dataDecimal");
var sortedInt = string.Format(SqlContext.SqlSyntax.ConvertIntegerToOrderableString, "intValue");
var sortedDate = string.Format(SqlContext.SqlSyntax.ConvertDateToOrderableString, "dateValue");
var sortedString = "COALESCE(varcharValue,'')"; // assuming COALESCE is ok for all syntaxes
var sortedDecimal = string.Format(SqlContext.SqlSyntax.ConvertDecimalToOrderableString, "decimalValue");
// variable query fragments that depend on what we are querying
string andVersion, andNewest, idField;
@@ -353,14 +353,14 @@ namespace Umbraco.Core.Persistence.Repositories
// needs to be an outer join since there's no guarantee that any of the nodes have values for this property
var outerJoinTempTable = $@"LEFT OUTER JOIN (
SELECT CASE
WHEN dataInt IS NOT NULL THEN {sortedInt}
WHEN dataDecimal IS NOT NULL THEN {sortedDecimal}
WHEN dataDate IS NOT NULL THEN {sortedDate}
WHEN intValue IS NOT NULL THEN {sortedInt}
WHEN decimalValue IS NOT NULL THEN {sortedDecimal}
WHEN dateValue IS NOT NULL THEN {sortedDate}
ELSE {sortedString}
END AS CustomPropVal,
cd.{idField} AS CustomPropValContentId
FROM {table} cd
INNER JOIN cmsPropertyData cpd ON cpd.contentNodeId = cd.{idField}{andVersion}
INNER JOIN cmsPropertyData cpd ON cpd.nodeId = cd.{idField}{andVersion}
INNER JOIN cmsPropertyType cpt ON cpt.Id = cpd.propertytypeId
WHERE cpt.Alias = @{sql.Arguments.Length}{andNewest}) AS CustomPropData
ON CustomPropData.CustomPropValContentId = umbracoNode.id "; // trailing space is important!
@@ -731,8 +731,8 @@ INNER JOIN cmsPropertyType
ON cmsPropertyData.propertytypeid = cmsPropertyType.id
INNER JOIN
(" + string.Format(parsedOriginalSql, "cmsContent.nodeId, cmsContentVersion.VersionId") + @") as docData
ON cmsPropertyData.versionId = docData.VersionId AND cmsPropertyData.contentNodeId = docData.nodeId
ORDER BY contentNodeId, versionId, propertytypeid
ON cmsPropertyData.versionId = docData.VersionId AND cmsPropertyData.nodeId = docData.nodeId
ORDER BY nodeId, versionId, propertytypeid
", docSql.Arguments);
//This does NOT fetch all data into memory in a list, this will read

View File

@@ -975,6 +975,7 @@
<Compile Include="Persistence\Migrations\Syntax\Delete\Index\IDeleteIndexOnColumnSyntax.cs" />
<Compile Include="Persistence\Migrations\Syntax\Delete\Table\DeleteTableBuilder.cs" />
<Compile Include="Persistence\Migrations\Syntax\Execute\ExecuteBuilder.cs" />
<Compile Include="Persistence\Migrations\Syntax\Execute\ExecuteBuilderExtensions.cs" />
<Compile Include="Persistence\Migrations\Syntax\Execute\Expressions\ExecuteCodeStatementExpression.cs" />
<Compile Include="Persistence\Migrations\Syntax\Execute\Expressions\ExecuteSqlStatementExpression.cs" />
<Compile Include="Persistence\Migrations\Syntax\Execute\IExecuteBuilder.cs" />
@@ -1013,6 +1014,7 @@
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionEight\AddLockObjects.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionEight\AddLockTable.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionEight\AddRedirectUrlTable.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionEight\VariantsMigration.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionEight\RefactorXmlColumns.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionEight\Seven1.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenFiveFive\AddLockObjects.cs" />

View File

@@ -0,0 +1,216 @@
using System.Linq;
using Moq;
using NUnit.Framework;
using Semver;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Migrations;
using Umbraco.Core.Persistence.Migrations.Initial;
using Umbraco.Core.Persistence.Migrations.Syntax.Execute;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Services;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.Testing;
namespace Umbraco.Tests.Migrations
{
[TestFixture]
[UmbracoTest(Database = UmbracoTestOptions.Database.NewEmptyPerTest)]
public class AdvancedMigrationTests : TestWithDatabaseBase
{
[Test]
public void CreateTableOfTDto()
{
var logger = new DebugDiagnosticsLogger();
using (var scope = ScopeProvider.CreateScope())
{
var database = scope.Database;
var context = new MigrationContext(database, logger);
var runner = new MigrationRunner(
Mock.Of<IMigrationCollectionBuilder>(),
Mock.Of<IMigrationEntryService>(),
logger,
new SemVersion(0), // 0.0.0
new SemVersion(1), // 1.0.0
"Test",
// explicit migrations
new CreateTableOfTDtoMigration(context)
);
var upgraded = runner.Execute(context);
Assert.IsTrue(upgraded);
var helper = new DatabaseSchemaHelper(database, logger);
var exists = helper.TableExist("umbracoNode");
Assert.IsTrue(exists);
scope.Complete();
}
}
[Test]
public void DeleteKeysAndIndexesOfTDto()
{
var logger = new DebugDiagnosticsLogger();
using (var scope = ScopeProvider.CreateScope())
{
var database = scope.Database;
var context = new MigrationContext(database, logger);
var runner = new MigrationRunner(
Mock.Of<IMigrationCollectionBuilder>(),
Mock.Of<IMigrationEntryService>(),
logger,
new SemVersion(0), // 0.0.0
new SemVersion(1), // 1.0.0
"Test",
// explicit migrations
new CreateTableOfTDtoMigration(context),
new DeleteKeysAndIndexesMigration(context)
);
var upgraded = runner.Execute(context);
Assert.IsTrue(upgraded);
scope.Complete();
}
}
[Test]
public void CreateKeysAndIndexesOfTDto()
{
var logger = new DebugDiagnosticsLogger();
using (var scope = ScopeProvider.CreateScope())
{
var database = scope.Database;
var context = new MigrationContext(database, logger);
var runner = new MigrationRunner(
Mock.Of<IMigrationCollectionBuilder>(),
Mock.Of<IMigrationEntryService>(),
logger,
new SemVersion(0), // 0.0.0
new SemVersion(1), // 1.0.0
"Test",
// explicit migrations
new CreateTableOfTDtoMigration(context),
new DeleteKeysAndIndexesMigration(context),
new CreateKeysAndIndexesOfTDtoMigration(context)
);
var upgraded = runner.Execute(context);
Assert.IsTrue(upgraded);
scope.Complete();
}
}
[Test]
public void CreateKeysAndIndexes()
{
var logger = new DebugDiagnosticsLogger();
using (var scope = ScopeProvider.CreateScope())
{
var database = scope.Database;
var context = new MigrationContext(database, logger);
var runner = new MigrationRunner(
Mock.Of<IMigrationCollectionBuilder>(),
Mock.Of<IMigrationEntryService>(),
logger,
new SemVersion(0), // 0.0.0
new SemVersion(1), // 1.0.0
"Test",
// explicit migrations
new CreateTableOfTDtoMigration(context),
new DeleteKeysAndIndexesMigration(context),
new CreateKeysAndIndexesMigration(context)
);
var upgraded = runner.Execute(context);
Assert.IsTrue(upgraded);
scope.Complete();
}
}
[Migration("1.0.0", 0, "Test")]
public class CreateTableOfTDtoMigration : MigrationBase
{
public CreateTableOfTDtoMigration(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
// creates Node table with keys, indexes, etc
Create.Table<NodeDto>();
}
}
[Migration("1.0.0", 1, "Test")]
public class DeleteKeysAndIndexesMigration : MigrationBase
{
public DeleteKeysAndIndexesMigration(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
// drops Node table keys and indexes
//Execute.DropKeysAndIndexes("umbracoNode");
// drops *all* tables keys and indexes
Execute.DropKeysAndIndexes();
}
}
[Migration("1.0.0", 2, "Test")]
public class CreateKeysAndIndexesOfTDtoMigration : MigrationBase
{
public CreateKeysAndIndexesOfTDtoMigration(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
// creates Node table keys and indexes
Create.KeysAndIndexes<NodeDto>();
}
}
[Migration("1.0.0", 3, "Test")]
public class CreateKeysAndIndexesMigration : MigrationBase
{
public CreateKeysAndIndexesMigration(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
// creates *all* tables keys and indexes
foreach (var x in DatabaseSchemaCreation.OrderedTables)
{
// ok - for tests, restrict to Node
if (x.Value != typeof(NodeDto)) continue;
Create.KeysAndIndexes(x.Value);
}
}
}
}
}

View File

@@ -1,71 +0,0 @@
using Moq;
using NUnit.Framework;
using Semver;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Migrations;
using Umbraco.Core.Services;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.Testing;
namespace Umbraco.Tests.Migrations
{
[TestFixture]
[UmbracoTest(Database = UmbracoTestOptions.Database.NewEmptyPerTest)]
public class CreateTableMigrationTests : TestWithDatabaseBase
{
[Test]
public void CreateTableOfTDto()
{
var logger = new DebugDiagnosticsLogger();
using (var scope = ScopeProvider.CreateScope())
{
var database = scope.Database;
var context = new MigrationContext(database, logger);
var runner = new MigrationRunner(
Mock.Of<IMigrationCollectionBuilder>(),
Mock.Of<IMigrationEntryService>(),
logger,
new SemVersion(0), // 0.0.0
new SemVersion(1), // 1.0.0
"Test",
// explicit migrations
new CreateTableOfTDtoMigration(context)
);
var upgraded = runner.Execute(context);
Assert.IsTrue(upgraded);
var helper = new DatabaseSchemaHelper(database, logger);
var exists = helper.TableExist("umbracoNode");
Assert.IsTrue(exists);
scope.Complete();
}
}
[Migration("1.0.0", 0, "Test")]
public class CreateTableOfTDtoMigration : MigrationBase
{
public CreateTableOfTDtoMigration(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
Create.Table<NodeDto>();
}
public override void Down()
{
throw new WontImplementException();
}
}
}
}

View File

@@ -83,7 +83,7 @@ namespace Umbraco.Tests.Migrations
{
NodeId = n.NodeId,
PropertyTypeId = pt.Id,
Text = "text",
TextValue = "text",
VersionId = Guid.NewGuid()
};
database.Insert(data);
@@ -91,20 +91,20 @@ namespace Umbraco.Tests.Migrations
{
NodeId = n.NodeId,
PropertyTypeId = pt.Id,
Text = "<root><node title=\"\" type=\"\" newwindow=\"\" link=\"\" /></root>",
TextValue = "<root><node title=\"\" type=\"\" newwindow=\"\" link=\"\" /></root>",
VersionId = Guid.NewGuid()
};
database.Insert(data);
var migrationContext = new MigrationContext(database, Logger);
var migration = new UpdateRelatedLinksData(migrationContext);
migration.UpdateRelatedLinksDataDo(database);
migration.UpdateRelatedLinksDataDo(migrationContext);
data = database.Fetch<PropertyDataDto>("SELECT * FROM cmsPropertyData WHERE id=" + data.Id).FirstOrDefault();
Assert.IsNotNull(data);
Debug.Print(data.Text);
Debug.Print(data.TextValue);
Assert.AreEqual("[{\"title\":\"\",\"caption\":\"\",\"link\":\"\",\"newWindow\":false,\"type\":\"external\",\"internal\":null,\"edit\":false,\"isInternal\":false}]",
data.Text);
data.TextValue);
}
}

View File

@@ -135,7 +135,7 @@ namespace Umbraco.Tests.Persistence.Querying
expected.Select("*");
expected.From("[cmsPropertyData]");
expected.InnerJoin("[cmsPropertyType]").On("[cmsPropertyData].[propertytypeid] = [cmsPropertyType].[id]");
expected.Where("([cmsPropertyData].[contentNodeId] = @0)", 1050);
expected.Where("([cmsPropertyData].[nodeId] = @0)", 1050);
expected.Where("([cmsPropertyData].[versionId] = @0)", new Guid("2b543516-a944-4ee6-88c6-8813da7aaa07"));
var sql = Sql();

View File

@@ -327,7 +327,7 @@ namespace Umbraco.Tests.Persistence.Repositories
sql.Select("umbracoNode.*", "cmsContent.contentType", "cmsContentType.alias AS ContentTypeAlias", "cmsContentVersion.VersionId",
"cmsContentVersion.VersionDate", "cmsMember.Email",
"cmsMember.LoginName", "cmsMember.Password", "cmsPropertyData.id AS PropertyDataId", "cmsPropertyData.propertytypeid",
"cmsPropertyData.dataDate", "cmsPropertyData.dataInt", "cmsPropertyData.dataNtext", "cmsPropertyData.dataNvarchar",
"cmsPropertyData.dateValue", "cmsPropertyData.intValue", "cmsPropertyData.textValue", "cmsPropertyData.varcharValue",
"cmsPropertyType.id", "cmsPropertyType.Alias", "cmsPropertyType.Description",
"cmsPropertyType.Name", "cmsPropertyType.mandatory", "cmsPropertyType.validationRegExp",
"cmsPropertyType.sortOrder AS PropertyTypeSortOrder", "cmsPropertyType.propertyTypeGroupId",

View File

@@ -1150,10 +1150,10 @@ namespace Umbraco.Tests.Services
}
Assert.AreEqual(1, colResult.Count);
Assert.IsTrue(colResult.First().Date.HasValue);
Assert.IsFalse(colResult.First().Integer.HasValue);
Assert.IsNull(colResult.First().Text);
Assert.IsNull(colResult.First().VarChar);
Assert.IsTrue(colResult.First().DateValue.HasValue);
Assert.IsFalse(colResult.First().IntegerValue.HasValue);
Assert.IsNull(colResult.First().TextValue);
Assert.IsNull(colResult.First().VarcharValue);
}
[Test]

View File

@@ -233,7 +233,7 @@
<Compile Include="IO\ShadowFileSystemTests.cs" />
<Compile Include="Issues\U9560.cs" />
<Compile Include="Integration\ContentEventsTests.cs" />
<Compile Include="Migrations\CreateTableMigrationTests.cs" />
<Compile Include="Migrations\AdvancedMigrationTests.cs" />
<Compile Include="Migrations\MigrationIssuesTests.cs" />
<Compile Include="Models\Mapping\AutoMapper6Tests.cs" />
<Compile Include="Models\Mapping\UserModelMapperTests.cs" />