diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/UpdateRelatedLinksData.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/UpdateRelatedLinksData.cs index d1fb7018b7..89630c7ab5 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/UpdateRelatedLinksData.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/UpdateRelatedLinksData.cs @@ -36,10 +36,19 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven database.Fetch( "WHERE propertyTypeId in (SELECT id from cmsPropertyType where dataTypeID IN (@dataTypeIds))", new { dataTypeIds = dataTypeIds }); if (!propertyData.Any()) return string.Empty; - - var nodesIdsWithProperty = propertyData.Select(x => x.NodeId).Distinct(); - var cmsContentXmlEntries = database.Fetch( - "WHERE nodeId in (@nodeIds)", new { nodeIds = nodesIdsWithProperty }); + + var nodesIdsWithProperty = propertyData.Select(x => x.NodeId).Distinct().ToArray(); + + var cmsContentXmlEntries = new List(); + //We're doing an "IN" query here but SQL server only supports 2100 query parameters so we're going to split on that + // It would be better to do this as an INNER join + sub query but I don't have time for that at the moment and this is only run once + // so it's not a big deal. + var batches = nodesIdsWithProperty.InGroupsOf(2000); + foreach (var batch in batches) + { + cmsContentXmlEntries.AddRange(database.Fetch("WHERE nodeId in (@nodeIds)", new { nodeIds = batch })); + } + var propertyTypeIds = propertyData.Select(x => x.PropertyTypeId).Distinct(); var propertyTypes = database.Fetch( "WHERE id in (@propertyTypeIds)", new { propertyTypeIds = propertyTypeIds }); @@ -48,9 +57,25 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven { if (string.IsNullOrEmpty(data.Text) == false) { + XmlDocument xml; //fetch the current data (that's in xml format) - var xml = new XmlDocument(); - xml.LoadXml(data.Text); + try + { + xml = new XmlDocument(); + xml.LoadXml(data.Text); + } + catch (Exception ex) + { + LogHelper.Error("The data stored for property id " + data.Id + " on document " + data.NodeId + + " is not valid XML, the data will be removed because it cannot be converted to the new format. The value was: " + data.Text, ex); + + data.Text = ""; + database.Update(data); + + UpdateXmlTable(propertyTypes, data, cmsContentXmlEntries, database); + + continue; + } var links = new List(); @@ -82,23 +107,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven database.Update(data); - //now we need to update the cmsContentXml table - var propertyType = propertyTypes.SingleOrDefault(x => x.Id == data.PropertyTypeId); - if (propertyType != null) - { - 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.Text)); - database.Update(xmlItem); - } - } - } - + UpdateXmlTable(propertyTypes, data, cmsContentXmlEntries, database); } } @@ -110,5 +119,25 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven { throw new DataLossException("Cannot downgrade from a version 7 database to a prior version, the database schema has already been modified"); } + + private static void UpdateXmlTable(List propertyTypes, PropertyDataDto data, List cmsContentXmlEntries, Database database) + { + //now we need to update the cmsContentXml table + var propertyType = propertyTypes.SingleOrDefault(x => x.Id == data.PropertyTypeId); + if (propertyType != null) + { + 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.Text)); + database.Update(xmlItem); + } + } + } + } } }