/// <summary> /// /// </summary> /// <param name="context"></param> /// <param name="queryBuilder"></param> /// <param name="record"> </param> /// <param name="modifiedProperties"></param> protected override void DoToUpdateStatement(IMansionContext context, ModificationQueryBuilder queryBuilder, Record record, IPropertyBag modifiedProperties) { // check if the property is not modified int newOrder; if (!modifiedProperties.TryGet(context, PropertyName, out newOrder)) return; // check if the record contains a pointer NodePointer pointer; if (!record.TryGet(context, "pointer", out pointer)) throw new InvalidOperationException("Could not update this record because it did not contain a pointer"); // don't update order for root nodes if (pointer.Depth == 1) return; // do not allow values smaller than 1 if (newOrder < 1) throw new InvalidOperationException("Can not set orders smaller than 1"); // assemble parameter var newOrderParameterName = queryBuilder.AddParameter("newOrder", newOrder, DbType.Int32); var oldOrderParameterName = queryBuilder.AddParameter("oldOrder", record.Get<int>(context, PropertyName), DbType.Int32); var parentIdParameterName = queryBuilder.AddParameter("parentId", pointer.Parent.Id, DbType.Int32); // update the orders before updating the order of the current node queryBuilder.PrependQuery(string.Format("UPDATE [Nodes] SET [order] = [order] + 1 WHERE (parentId = {0}) AND ([order] < {1} AND [order] >= {2})", parentIdParameterName, oldOrderParameterName, newOrderParameterName)); queryBuilder.PrependQuery(string.Format("UPDATE [Nodes] SET [order] = [order] - 1 WHERE (parentId = {0}) AND ([order] > {1} AND [order] <= {2})", parentIdParameterName, oldOrderParameterName, newOrderParameterName)); // update the column queryBuilder.AddColumnValue(PropertyName, newOrderParameterName); }
/// <summary> /// Prepares an insert query. /// </summary> /// <param name="context"></param> /// <param name="connection">The connection.</param> /// <param name="transaction">The transaction.</param> /// <param name="record"></param> /// <returns></returns> public void Prepare(IMansionContext context, SqlConnection connection, SqlTransaction transaction, Record record) { // validate arguments if (connection == null) throw new ArgumentNullException("connection"); if (transaction == null) throw new ArgumentNullException("transaction"); if (record == null) throw new ArgumentNullException("record"); // retrieve the schema var type = typeService.Load(context, record.Type); var schema = Resolver.Resolve(context, type); // create the commands command = connection.CreateCommand(); command.CommandType = CommandType.Text; command.Transaction = transaction; // check if the record contains a pointer NodePointer pointer; if (record.TryGet(context, "pointer", out pointer)) { command.CommandText += string.Format(@"DELETE FROM [{0}] WHERE [{0}].[parentPointer] LIKE @pointer;", schema.RootTable.Name); command.Parameters.AddWithValue("pointer", pointer.PointerString + NodePointer.PointerSeparator + "%"); } command.CommandText += string.Format(@"DELETE FROM [{0}] WHERE [{0}].[id] = @id;", schema.RootTable.Name); command.Parameters.AddWithValue("id", record.Id); }
/// <summary> /// This method is called just before a node is updated by the repository. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="record"> </param> /// <param name="properties">The updated properties of the node.</param> protected override void DoBeforeUpdate(IMansionContext context, Record record, IPropertyBag properties) { // get the variables string currentTheme; var hasCurrentTheme = record.TryGet(context, "theme", out currentTheme) && !string.IsNullOrEmpty(currentTheme); string newTheme; var hasNewTheme = properties.TryGet(context, "theme", out newTheme) && !string.IsNullOrEmpty(newTheme); // do nothing when the page does not have a theme yet if (!hasCurrentTheme) return; // retrieve the schema of the current theme var currentThemeSchema = ColumnSchema.GetSchema(context, currentTheme); // retrieve the blocks of this page var repository = context.Repository; var blockNodeset = repository.RetrieveNodeset(context, new PropertyBag { {"baseType", "Block"}, {"parentSource", record} }); // check if a new theme is selected if (hasNewTheme) { // retrieve the schema of the new theme var newThemeSchema = ColumnSchema.GetSchema(context, newTheme); // loop through the blocks to find obsolete ones foreach (var blockNode in blockNodeset.Nodes) { // get the column of this block var column = blockNode.Get<string>(context, "column"); // check if this block lived in the old theme if (!currentThemeSchema.ContainsColumn(column)) continue; // check if the column exists in the new theme as well if (newThemeSchema.ContainsColumn(column)) continue; // block is obsolete delete it repository.DeleteNode(context, blockNode); } } else { // theme is removed, delete all the theme blocks foreach (var blockNode in blockNodeset.Nodes.Where(candidate => currentThemeSchema.ContainsColumn(candidate.Get<string>(context, "column")))) repository.DeleteNode(context, blockNode); } base.DoBeforeUpdate(context, record, properties); }
/// <summary> /// This method is called just after a node is created by the repository. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="record"> </param> /// <param name="properties">The properties from which the <paramref name="record"/> was constructed.</param> protected override void DoAfterCreate(IMansionContext context, Record record, IPropertyBag properties) { base.DoAfterCreate(context, record, properties); // check if a preferred term was specified Guid newPreferredTermGuid; if (!record.TryGet(context, "preferredTermGuid", out newPreferredTermGuid) || newPreferredTermGuid == Guid.Empty) return; // retrieve the preferredTermNode var newPreferredTermNode = context.Repository.RetrieveSingleNode(context, newPreferredTermGuid); if (newPreferredTermNode == null) return; // store the guid in the synonymGuids field context.Repository.UpdateNode(context, newPreferredTermNode, new PropertyBag { {"synonymGuids", newPreferredTermNode.Get(context, "synonymGuids", string.Empty).AppendNeedle(record.Get<string>(context, "guid"))} }); }
/// <summary> /// This method is called just before a node is updated by the repository. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="record"> </param> /// <param name="properties">The updated properties of the node.</param> protected override void DoBeforeUpdate(IMansionContext context, Record record, IPropertyBag properties) { // check if the layout was not modified string newLayoutName; if (!properties.TryGet(context, "layout", out newLayoutName)) return; // check if there was no old layout string oldLayoutName; if (!record.TryGet(context, "layout", out oldLayoutName)) return; // get the schemas var newColumnSchema = ColumnSchema.GetSchema(context, newLayoutName); var oldColumnSchema = ColumnSchema.GetSchema(context, oldLayoutName); // retrieve the blocks of this page var repository = context.Repository; var blockNodeset = repository.RetrieveNodeset(context, new PropertyBag { {"baseType", "Block"}, {"parentSource", record} }); // loop through all the nodes foreach (var blockNode in blockNodeset.Nodes) { // check if this block was not in a column of the old schema so it wont have to move to the new schema var columnName = blockNode.Get<string>(context, "column"); if (!oldColumnSchema.ContainsColumn(columnName)) continue; // check if the column is in the new schema as well so it wont have to move if (newColumnSchema.ContainsColumn(columnName)) continue; // move the block to the default column repository.UpdateNode(context, blockNode, new PropertyBag { {"column", newColumnSchema.DefaultColumn} }); } }
/// <summary> /// This method is called just before a node is updated by the repository. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="record"> </param> /// <param name="properties">The updated properties of the node.</param> protected override void DoBeforeUpdate(IMansionContext context, Record record, IPropertyBag properties) { base.DoBeforeUpdate(context, record, properties); // check if the preferred term has changed Guid newPreferredTermGuid; if (!properties.TryGet(context, "preferredTermGuid", out newPreferredTermGuid)) return; // delete the old link if it exists var recordGuidString = record.Get<string>(context, "guid"); Guid currentPreferredTermGuid; if (record.TryGet(context, "preferredTermGuid", out currentPreferredTermGuid) && currentPreferredTermGuid != Guid.Empty) { // retrieve the old record var currentPreferredTermNode = context.Repository.RetrieveSingleNode(context, currentPreferredTermGuid); // remove the link, if the target was found if (currentPreferredTermNode != null) { // store the guid in the synonymGuids field context.Repository.UpdateNode(context, currentPreferredTermNode, new PropertyBag { {"synonymGuids", currentPreferredTermNode.Get(context, "synonymGuids", string.Empty).RemoveNeedle(recordGuidString)} }); } } // check if there is no new synonym if (newPreferredTermGuid == Guid.Empty) return; // retrieve the preferredTermNode var newPreferredTermNode = context.Repository.RetrieveSingleNode(context, newPreferredTermGuid); if (newPreferredTermNode == null) return; // store the guid in the synonymGuids field context.Repository.UpdateNode(context, newPreferredTermNode, new PropertyBag { {"synonymGuids", newPreferredTermNode.Get(context, "synonymGuids", string.Empty).AppendNeedle(recordGuidString)} }); }
/// <summary> /// /// </summary> /// <param name="context"></param> /// <param name="queryBuilder"></param> /// <param name="record"> </param> /// <param name="modifiedProperties"></param> protected override void DoToUpdateStatement(IMansionContext context, ModificationQueryBuilder queryBuilder, Record record, IPropertyBag modifiedProperties) { // allow update of relational column on special cases, most likely used when fixing the repository integrity if (modifiedProperties.Get(context, "_allowRelationPropertiesUpdate", false)) { string name; if (modifiedProperties.TryGet(context, "name", out name)) queryBuilder.AddColumnValue("name", name, DbType.String); string type; if (modifiedProperties.TryGet(context, "type", out type)) queryBuilder.AddColumnValue("type", type, DbType.String); int depth; if (modifiedProperties.TryGet(context, "depth", out depth)) queryBuilder.AddColumnValue("depth", depth, DbType.Int32); int parentId; if (modifiedProperties.TryGet(context, "parentId", out parentId)) queryBuilder.AddColumnValue("parentId", parentId, DbType.Int32); string parentPointer; if (modifiedProperties.TryGet(context, "parentPointer", out parentPointer)) queryBuilder.AddColumnValue("parentPointer", parentPointer, DbType.String); string parentPath; if (modifiedProperties.TryGet(context, "parentPath", out parentPath)) queryBuilder.AddColumnValue("parentPath", parentPath, DbType.String); string parentStructure; if (modifiedProperties.TryGet(context, "parentStructure", out parentStructure)) queryBuilder.AddColumnValue("parentStructure", parentStructure, DbType.String); return; } // make sure the relational intgrety is not comprimised if (modifiedProperties.Names.Intersect(ReservedPropertyName, StringComparer.OrdinalIgnoreCase).Any()) throw new InvalidOperationException("The relational properties can not be changed"); // get the pointer NodePointer pointer; if (!record.TryGet(context, "pointer", out pointer)) throw new InvalidOperationException("Could not update this record because it did not contain a pointer"); // add the id an pointer parameters var idParameterName = queryBuilder.AddParameter("id", pointer.Id, DbType.Int32); var pointerParameterName = queryBuilder.AddParameter("pointer", pointer.PointerString + "-%", DbType.String); // check if the name changed string newName; if (modifiedProperties.TryGetAndRemove(context, "name", out newName)) { newName = newName.Trim(); if (string.IsNullOrEmpty(newName)) throw new InvalidOperationException("Can not update column name with empty string"); if (newName.Contains(NodePointer.PathSeparator)) throw new InvalidOperationException(string.Format("Name '{0}' contains invalid characters", newName)); if (!pointer.Name.Equals(newName)) { // add the name column modification queryBuilder.AddColumnValue("name", newName, DbType.String); // update the paths var oldPathLengthParameterName = queryBuilder.AddParameter("oldPathLength", pointer.PathString.Length + 1, DbType.String); var newPathParameterName = queryBuilder.AddParameter("newPath", NodePointer.Rename(pointer, newName).PathString + NodePointer.PathSeparator, DbType.String); queryBuilder.AppendQuery(string.Format(@" UPDATE [Nodes] SET [parentPath] = {0} + RIGHT( [parentPath], LEN( [parentPath] ) - {1} ) WHERE ( [parentId] = {2} OR [parentPointer] LIKE {3} )", newPathParameterName, oldPathLengthParameterName, idParameterName, pointerParameterName)); } } // check if the type changed string newType; if (modifiedProperties.TryGetAndRemove(context, "type", out newType)) { newType = newType.Trim(); if (string.IsNullOrEmpty(newType)) throw new InvalidOperationException("Can not update column type with empty string"); if (newType.Contains(NodePointer.StructureSeparator)) throw new InvalidOperationException(string.Format("Type '{0}' contains invalid characters", newType)); if (!string.IsNullOrEmpty(newType) && !pointer.Type.Equals(newType, StringComparison.OrdinalIgnoreCase)) { // add the name column modification queryBuilder.AddColumnValue("type", newType, DbType.String); // update the structures var newStructureParameterName = queryBuilder.AddParameter("newStructure", NodePointer.ChangeType(pointer, newType).StructureString + NodePointer.StructureSeparator, DbType.String); var oldStructureLengthParameterName = queryBuilder.AddParameter("oldStructureLength", pointer.StructureString.Length + 1, DbType.Int32); queryBuilder.AppendQuery(string.Format("UPDATE [Nodes] SET [parentStructure] = {0} + RIGHT( [parentStructure], LEN( [parentStructure] ) - {1} ) WHERE ( [parentId] = {2} OR [parentPointer] LIKE {3} )", newStructureParameterName, oldStructureLengthParameterName, idParameterName, pointerParameterName)); } } }
/// <summary> /// Get the Job timespan /// </summary> /// <param name="context"></param> /// <param name="jobRecord"></param> /// <returns></returns> private static TimeSpan GetJobTimeSpan(IMansionContext context, Record jobRecord) { var triggerTimeSpan = new TimeSpan(); int triggerInterval; if (jobRecord.TryGet(context, "triggerIntervalSeconds", out triggerInterval)) triggerTimeSpan = triggerTimeSpan.Add(TimeSpan.FromSeconds(triggerInterval)); if (jobRecord.TryGet(context, "triggerIntervalMinutes", out triggerInterval)) triggerTimeSpan = triggerTimeSpan.Add(TimeSpan.FromMinutes(triggerInterval)); if (jobRecord.TryGet(context, "triggerIntervalHours", out triggerInterval)) triggerTimeSpan = triggerTimeSpan.Add(TimeSpan.FromHours(triggerInterval)); return triggerTimeSpan; }