public void SetAutonumbers(XrmEntityPlugin plugin) { if (plugin.IsMessage(PluginMessage.Create) && plugin.IsStage(PluginStage.PreOperationEvent)) { SetAutonumbers(plugin.TargetEntity); } }
/// <summary> /// Processes plugin for a type type rolled up /// </summary> /// <param name="plugin"></param> public void ExecuteRollupPlugin(XrmEntityPlugin plugin) { if (plugin.IsMessage(PluginMessage.Create, PluginMessage.Update, PluginMessage.Delete) && plugin.IsStage(PluginStage.PostEvent) && plugin.IsMode(PluginMode.Synchronous)) { var rollupsToProcess = GetRollupsForRolledupType(plugin.TargetType).ToArray(); var dictionaryForDifferences = new Dictionary <string, Dictionary <Guid, List <UpdateMeta> > >(); Action <string, Guid, string, object, LookupRollup> addValueToApply = (type, id, field, val, rollup) => { if (!dictionaryForDifferences.ContainsKey(type)) { dictionaryForDifferences.Add(type, new Dictionary <Guid, List <UpdateMeta> >()); } if (!dictionaryForDifferences[type].ContainsKey(id)) { dictionaryForDifferences[type].Add(id, new List <UpdateMeta>()); } dictionaryForDifferences[type][id].Add(new UpdateMeta(field, rollup, val)); }; foreach (var rollup in rollupsToProcess) { //capture required facts in the plugin context to process our ifs and elses var metConditionsBefore = XrmEntity.MeetsFilter(plugin.GetFieldFromPreImage, rollup.Filter); var meetsConditionsAfter = plugin.MessageName == PluginMessage.Delete ? false : XrmEntity.MeetsFilter(plugin.GetField, rollup.Filter); var linkedIdBefore = XrmEntity.GetLookupType(plugin.GetFieldFromPreImage(rollup.LookupName)) == rollup.RecordTypeWithRollup ? plugin.GetLookupGuidPreImage(rollup.LookupName) : null; var linkedIdAfter = plugin.MessageName == PluginMessage.Delete || XrmEntity.GetLookupType(plugin.GetField(rollup.LookupName)) != rollup.RecordTypeWithRollup ? null : plugin.GetLookupGuid(rollup.LookupName); var isValueChanging = rollup.FieldRolledup != null && plugin.FieldChanging(rollup.FieldRolledup); var isOrderByChanging = rollup.OrderByField != null && plugin.FieldChanging(rollup.OrderByField); if (AllowsDifferenceChange(rollup.RollupType)) { //this covers scenarios which require changing the value in a parent record if (linkedIdBefore.HasValue && linkedIdBefore == linkedIdAfter) { //the same record linked before and after if (metConditionsBefore && meetsConditionsAfter) { //if part of Rollup before and after if (isValueChanging) { //and the value is changing then apply difference if (rollup.RollupType == RollupType.Sum) { addValueToApply(rollup.RecordTypeWithRollup, linkedIdAfter.Value, rollup.RollupField, GetDifferenceToApply(plugin.GetFieldFromPreImage(rollup.FieldRolledup), plugin.GetField(rollup.FieldRolledup)), rollup); } else if (rollup.RollupType == RollupType.Count) { //for count only adjust if changing between null and not null if (plugin.GetFieldFromPreImage(rollup.FieldRolledup) == null) { addValueToApply(rollup.RecordTypeWithRollup, linkedIdAfter.Value, rollup.RollupField, 1, rollup); } else if (plugin.GetField(rollup.FieldRolledup) == null) { addValueToApply(rollup.RecordTypeWithRollup, linkedIdAfter.Value, rollup.RollupField, -1, rollup); } } } } if (!metConditionsBefore && meetsConditionsAfter) { //if was not part of Rollup before but is now apply the entire value if (rollup.RollupType == RollupType.Sum) { addValueToApply(rollup.RecordTypeWithRollup, linkedIdAfter.Value, rollup.RollupField, plugin.GetField(rollup.FieldRolledup), rollup); } else if (rollup.RollupType == RollupType.Count) { addValueToApply(rollup.RecordTypeWithRollup, linkedIdAfter.Value, rollup.RollupField, 1, rollup); } } if (metConditionsBefore && !meetsConditionsAfter) { //if was part of Rollup before but not now apply the entire value negative if (rollup.RollupType == RollupType.Sum) { addValueToApply(rollup.RecordTypeWithRollup, linkedIdAfter.Value, rollup.RollupField, GetNegative(plugin.GetFieldFromPreImage(rollup.FieldRolledup)), rollup); } else if (rollup.RollupType == RollupType.Count) { addValueToApply(rollup.RecordTypeWithRollup, linkedIdAfter.Value, rollup.RollupField, -1, rollup); } } } else { //different parent linked before and after if (linkedIdBefore.HasValue && metConditionsBefore) { //if was part of previous linked records Rollup then negate the previous value if (rollup.RollupType == RollupType.Sum) { addValueToApply(rollup.RecordTypeWithRollup, linkedIdBefore.Value, rollup.RollupField, GetNegative(plugin.GetFieldFromPreImage(rollup.FieldRolledup)), rollup); } else if (rollup.RollupType == RollupType.Count) { addValueToApply(rollup.RecordTypeWithRollup, linkedIdBefore.Value, rollup.RollupField, -1, rollup); } } if (linkedIdAfter.HasValue && meetsConditionsAfter) { //if part of new linked records Rollup then apply the entire value if (rollup.RollupType == RollupType.Sum) { addValueToApply(rollup.RecordTypeWithRollup, linkedIdAfter.Value, rollup.RollupField, plugin.GetField(rollup.FieldRolledup), rollup); } else if (rollup.RollupType == RollupType.Count) { addValueToApply(rollup.RecordTypeWithRollup, linkedIdAfter.Value, rollup.RollupField, 1, rollup); } } } } else { //these ones just recalculate on the parent record(s) var isDependencyChanging = false; switch (plugin.MessageName) { case PluginMessage.Delete: { isDependencyChanging = linkedIdBefore.HasValue && metConditionsBefore; break; } case PluginMessage.Update: { if (linkedIdBefore != linkedIdAfter || isValueChanging) { isDependencyChanging = true; } else if (isOrderByChanging) { isDependencyChanging = true; } else { isDependencyChanging = metConditionsBefore != meetsConditionsAfter; } break; } case PluginMessage.Create: { isDependencyChanging = linkedIdAfter.HasValue && (rollup.FieldRolledup == null || isValueChanging) && meetsConditionsAfter; break; } } if (isDependencyChanging) { var processPreReferenced = false; var processPostReferenced = false; //If they aren't the same do both if (!XrmEntity.FieldsEqual(linkedIdBefore, linkedIdAfter)) { processPreReferenced = true; processPostReferenced = true; } //else just do the first not null one else { if (linkedIdBefore.HasValue) { processPreReferenced = true; } else { processPostReferenced = true; } } if (processPreReferenced && linkedIdBefore.HasValue) { addValueToApply(rollup.RecordTypeWithRollup, linkedIdBefore.Value, rollup.RollupField, null, rollup); } if (processPostReferenced && linkedIdAfter.HasValue) { addValueToApply(rollup.RecordTypeWithRollup, linkedIdAfter.Value, rollup.RollupField, null, rollup); } } } } //apply all required changes to parents we captured //type -> ids -> fields . values foreach (var item in dictionaryForDifferences) { var targetType = item.Key; foreach (var idUpdates in item.Value) { var id = idUpdates.Key; //lock the parent record then retreive it plugin.XrmService.SetField(targetType, id, "modifiedon", DateTime.UtcNow); var fieldsForUpdating = idUpdates.Value.Select(kv => kv.FieldName).ToArray(); var targetRecord = plugin.XrmService.Retrieve(targetType, id, idUpdates.Value.Select(kv => kv.FieldName)); //update the fields foreach (var fieldUpdate in idUpdates.Value) { if (AllowsDifferenceChange(fieldUpdate.Rollup.RollupType)) { targetRecord.SetField(fieldUpdate.FieldName, XrmEntity.SumFields(new[] { fieldUpdate.DifferenceValue, targetRecord.GetField(fieldUpdate.FieldName) })); } else { targetRecord.SetField(fieldUpdate.FieldName, GetRollup(fieldUpdate.Rollup, id)); } } plugin.XrmService.Update(targetRecord, fieldsForUpdating); } } } }
public void SetAutonumbers(XrmEntityPlugin plugin) { if (plugin.IsMessage(PluginMessage.Create) && plugin.IsStage(PluginStage.PreOperationEvent)) { SetAutonumbers(plugin.TargetEntity); } }
private void ExecuteDependencyPluginDifferences(XrmEntityPlugin plugin) { var dictionaryForDifferences = new Dictionary <string, Dictionary <Guid, List <KeyValuePair <string, object> > > >(); var rollupsToProcess = GetRollupsForRolledupType(plugin.TargetType) .Where(a => AllowsDifferenceChange(a.RollupType)) .ToArray(); if (plugin.IsMessage(PluginMessage.Create, PluginMessage.Update, PluginMessage.Delete) && plugin.IsStage(PluginStage.PostEvent) && plugin.IsMode(PluginMode.Synchronous)) { //this dictionary will capture the changes we need to apply to parent records for all Rollups //type -> ids -> fields . values Action <string, Guid, string, object> addDifferenceToApply = (type, id, field, val) => { if (!dictionaryForDifferences.ContainsKey(type)) { dictionaryForDifferences.Add(type, new Dictionary <Guid, List <KeyValuePair <string, object> > >()); } if (!dictionaryForDifferences[type].ContainsKey(id)) { dictionaryForDifferences[type].Add(id, new List <KeyValuePair <string, object> >()); } dictionaryForDifferences[type][id].Add(new KeyValuePair <string, object>(field, val)); }; foreach (var rollup in rollupsToProcess) { if (rollup.LinkEntity != null) { throw new NotImplementedException("Rollups with a LinkEntity are not implemented for the ProcessAsDifferences method"); } //capture required facts in the plugin context to process our ifs and elses var metConditionsBefore = XrmEntity.MeetsConditions(plugin.GetFieldFromPreImage, rollup.Filters); var meetsConditionsAfter = plugin.MessageName == PluginMessage.Delete ? false : XrmEntity.MeetsConditions(plugin.GetField, rollup.Filters); var linkedIdBefore = XrmEntity.GetLookupType(plugin.GetFieldFromPreImage(rollup.LookupName)) == rollup.RecordTypeWithRollup ? plugin.GetLookupGuidPreImage(rollup.LookupName) : (Guid?)null; var linkedIdAfter = plugin.MessageName == PluginMessage.Delete || XrmEntity.GetLookupType(plugin.GetField(rollup.LookupName)) != rollup.RecordTypeWithRollup ? (Guid?)null : plugin.GetLookupGuid(rollup.LookupName); var isValueChanging = plugin.FieldChanging(rollup.FieldRolledup); //this covers all scenarios I thought of which require changing the value in a parent record if (linkedIdBefore.HasValue && linkedIdBefore == linkedIdAfter) { //the same record linked before and after if (metConditionsBefore && meetsConditionsAfter) { //if part of Rollup before and after if (isValueChanging) { //and the value is changing then apply difference if (rollup.RollupType == RollupType.Sum) { addDifferenceToApply(rollup.RecordTypeWithRollup, linkedIdAfter.Value, rollup.RollupField, GetDifferenceToApply(plugin.GetFieldFromPreImage(rollup.FieldRolledup), plugin.GetField(rollup.FieldRolledup))); } else if (rollup.RollupType == RollupType.Count) { //for count only adjust if changing between null and not null if (plugin.GetFieldFromPreImage(rollup.FieldRolledup) == null) { addDifferenceToApply(rollup.RecordTypeWithRollup, linkedIdAfter.Value, rollup.RollupField, 1); } else if (plugin.GetField(rollup.FieldRolledup) == null) { addDifferenceToApply(rollup.RecordTypeWithRollup, linkedIdAfter.Value, rollup.RollupField, -1); } } } } if (!metConditionsBefore && meetsConditionsAfter) { //if was not part of Rollup before but is now apply the entire value if (rollup.RollupType == RollupType.Sum) { addDifferenceToApply(rollup.RecordTypeWithRollup, linkedIdAfter.Value, rollup.RollupField, plugin.GetField(rollup.FieldRolledup)); } else if (rollup.RollupType == RollupType.Count) { addDifferenceToApply(rollup.RecordTypeWithRollup, linkedIdAfter.Value, rollup.RollupField, 1); } } if (metConditionsBefore && !meetsConditionsAfter) { //if was part of Rollup before but not now apply the entire value negative if (rollup.RollupType == RollupType.Sum) { addDifferenceToApply(rollup.RecordTypeWithRollup, linkedIdAfter.Value, rollup.RollupField, GetNegative(plugin.GetFieldFromPreImage(rollup.FieldRolledup))); } else if (rollup.RollupType == RollupType.Count) { addDifferenceToApply(rollup.RecordTypeWithRollup, linkedIdAfter.Value, rollup.RollupField, -1); } } } else { //different parent linked before and after if (linkedIdBefore.HasValue && metConditionsBefore) { //if was part of previous linked records Rollup then negate the previous value if (rollup.RollupType == RollupType.Sum) { addDifferenceToApply(rollup.RecordTypeWithRollup, linkedIdBefore.Value, rollup.RollupField, GetNegative(plugin.GetFieldFromPreImage(rollup.FieldRolledup))); } else if (rollup.RollupType == RollupType.Count) { addDifferenceToApply(rollup.RecordTypeWithRollup, linkedIdBefore.Value, rollup.RollupField, -1); } } if (linkedIdAfter.HasValue && meetsConditionsAfter) { //if part of new linked records Rollup then apply the entire value if (rollup.RollupType == RollupType.Sum) { addDifferenceToApply(rollup.RecordTypeWithRollup, linkedIdAfter.Value, rollup.RollupField, plugin.GetField(rollup.FieldRolledup)); } else if (rollup.RollupType == RollupType.Count) { addDifferenceToApply(rollup.RecordTypeWithRollup, linkedIdAfter.Value, rollup.RollupField, 1); } } } } } if (dictionaryForDifferences.Any()) { plugin.Trace("Updating Rollup Differences"); foreach (var item in dictionaryForDifferences) { foreach (var field in item.Value) { foreach (var value in field.Value) { plugin.Trace("Updating " + item.Key + " " + field.Key + " " + value.Key + " " + value.Value + (value.Value == null ? "(null)" : (" (" + value.Value.GetType().Name + ")"))); } } } } //apply all required changes to parents we captured //type -> ids -> fields . values foreach (var item in dictionaryForDifferences) { var targetType = item.Key; foreach (var idUpdates in item.Value) { var id = idUpdates.Key; //lock the parent record then retreive it plugin.XrmService.SetField(targetType, id, "modifiedon", DateTime.UtcNow); var fieldsForUpdating = idUpdates.Value.Select(kv => kv.Key).ToArray(); var targetRecord = plugin.XrmService.Retrieve(targetType, id, idUpdates.Value.Select(kv => kv.Key)); //update the fields foreach (var fieldUpdate in idUpdates.Value) { targetRecord.SetField(fieldUpdate.Key, XrmEntity.SumFields(new[] { fieldUpdate.Value, targetRecord.GetField(fieldUpdate.Key) })); } plugin.XrmService.Update(targetRecord, fieldsForUpdating); } } }