private bool ReadAndLogSolutionImportJobStatus(Guid jobid) { log.StartSection("ReadAndLogSolutionImportJobStatus " + jobid); var success = false; var job = CintDynEntity.Retrieve("importjob", jobid, new ColumnSet("startedon", "completedon", "progress", "data"), crmsvc, log); if (job != null) { var name = "?"; var result = "?"; var err = ""; var start = job.Property("startedon", DateTime.MinValue); var complete = job.Property("completedon", DateTime.MinValue); var time = complete != null && start != null?complete.Subtract(start) : new TimeSpan(); var prog = job.Property <double>("progress", 0); if (job.Contains("data", true)) { var doc = new XmlDocument(); var data = job.Property("data", ""); log.Log("Job data length: {0}", data.Length); if (!string.IsNullOrWhiteSpace(data)) { doc.LoadXml(data); var namenode = doc.SelectSingleNode("//solutionManifest/UniqueName"); if (namenode != null) { name = namenode.InnerText; } var resultnode = doc.SelectSingleNode("//solutionManifest/result/@result"); if (resultnode != null) { result = resultnode.Value; } var errnode = doc.SelectSingleNode("//solutionManifest/result/@errortext"); if (errnode != null) { err = errnode.Value; } } } if (prog >= 100 && result == "success") { SendLine("Solution {0} imported in {1}", name, time); log.Log("Result: {0}\nError: {1}\nTime: {2}", result, err, time); success = true; } else { SendLine("Solution: {0}", name); SendLine("Result: {0}", result); SendLine("Error: {0}", err); SendLine("Progress: {0}", prog); SendLine("Time: {0}", time); } } log.Log("Returning: {0}", success); log.EndSection(); return(success); }
private CintDynEntityCollection GetMatchingRecords(CintDynEntity cdEntity, List <string> matchattributes, List <string> updateattributes, bool preretrieveall, ref CintDynEntityCollection cAllRecordsToMatch) { log.StartSection(MethodBase.GetCurrentMethod().Name); CintDynEntityCollection matches = null; var allattributes = new List <string>(); allattributes.Add(cdEntity.PrimaryIdAttribute); if (cdEntity.Contains("ownerid")) { allattributes.Add("ownerid"); } if (cdEntity.Contains("statecode") || cdEntity.Contains("statuscode")) { allattributes.Add("statecode"); allattributes.Add("statuscode"); } allattributes = allattributes.Union(matchattributes.Union(updateattributes)).ToList(); if (preretrieveall) { if (cAllRecordsToMatch == null) { cAllRecordsToMatch = GetAllRecordsForMatching(allattributes, cdEntity); } matches = GetMatchingRecordsFromPreRetrieved(matchattributes, cdEntity, cAllRecordsToMatch); } else { QueryExpression qMatch = new QueryExpression(cdEntity.Name); // We need to be able to see if any attributes have changed, so lets make sure matching records have all the attributes that will be updated qMatch.ColumnSet = new ColumnSet(allattributes.ToArray()); foreach (var matchattr in matchattributes) { object value = null; if (cdEntity.Entity.Contains(matchattr)) { value = CintEntity.AttributeToBaseType(cdEntity.Entity[matchattr]); } else if (matchattr == cdEntity.PrimaryIdAttribute) { value = cdEntity.Id; } if (value != null) { CintQryExp.AppendCondition(qMatch.Criteria, LogicalOperator.And, matchattr, Microsoft.Xrm.Sdk.Query.ConditionOperator.Equal, value); } else { CintQryExp.AppendCondition(qMatch.Criteria, LogicalOperator.And, matchattr, Microsoft.Xrm.Sdk.Query.ConditionOperator.Null, null); } } #if DEBUG log.Log("Finding matches for {0}:\n{1}", cdEntity, CintQryExp.ConvertToFetchXml(qMatch, crmsvc)); #endif matches = CintDynEntity.RetrieveMultiple(crmsvc, qMatch, log); } log.EndSection(); return(matches); }
private CintDynEntityCollection GetExistingSolutions() { CintDynEntityCollection cSolutions = CintDynEntity.RetrieveMultiple(crmsvc, "solution", new string[] { "isvisible" }, new object[] { true }, new ColumnSet("solutionid", "uniquename", "friendlyname", "version", "ismanaged"), log); return(cSolutions); }
/// <summary> /// Creates the provided web resource /// </summary> /// <param name="webResource">Web resource to create</param> internal static Guid CreateWebResource(this CintContainer container, CintDynEntity webResource) { try { return(webResource.Create()); } catch (Exception error) { throw new Exception("Error while creating web resource: " + error.Message); } }
/// <summary> /// Deletes the provided web resource /// </summary> /// <param name="webResource">Web resource to delete</param> internal static void DeleteWebResource(this CintContainer container, CintDynEntity webResource) { try { webResource.Delete(); } catch (Exception error) { throw new Exception("Error while deleting web resource: " + error.Message); } }
/// <summary> /// Retrieves a specific web resource from its unique identifier /// </summary> /// <param name="webresourceId">Web resource unique identifier</param> /// <returns>Web resource</returns> internal static CintDynEntity RetrieveWebResource(this CintContainer container, Guid webresourceId) { try { return(CintDynEntity.Retrieve(container, "webresource", webresourceId, new ColumnSet(true))); } catch (Exception error) { throw new Exception("Error while retrieving web resource: " + error.Message); } }
private void UpdateAssembly(CintDynEntity plugin) { WriteVerbose("Reading assembly file " + AssemblyFile); var file = this.ReadFile(AssemblyFile); WriteVerbose("Adding Base64String to entity"); var updateplugin = plugin.Clone(true); updateplugin.AddProperty("version", fileversion.ToString()); updateplugin.AddProperty("content", Convert.ToBase64String(file)); WriteObject("Saving updated assembly record"); updateplugin.Save(); }
private CintDynEntityCollection GetAllRecordsForMatching(List <string> allattributes, CintDynEntity cdEntity) { log.StartSection(MethodBase.GetCurrentMethod().Name); QueryExpression qMatch = new QueryExpression(cdEntity.Name); qMatch.ColumnSet = new ColumnSet(allattributes.ToArray()); #if DEBUG log.Log("Retrieving all records for {0}:\n{1}", cdEntity.Name, CintQryExp.ConvertToFetchXml(qMatch, crmsvc)); #endif CintDynEntityCollection matches = CintDynEntity.RetrieveMultiple(crmsvc, qMatch, log); SendLine("Pre-retrieved {0} records for matching", matches.Count); log.EndSection(); return(matches); }
private CintDynEntity GetAssembly(CintContainer container) { WriteObject($"Reading assembly file {AssemblyFile}"); var file = ReadFile(AssemblyFile); WriteVerbose("Loading assembly file"); var assembly = Assembly.Load(file); var chunks = assembly.FullName.Split(new string[] { ", ", "Version=", "Culture=", "PublicKeyToken=" }, StringSplitOptions.RemoveEmptyEntries); filename = chunks[0]; fileversion = new Version(chunks[1]); fileculture = chunks[2]; filetoken = chunks[3]; WriteObject($"Loaded assembly {filename} {fileversion}"); WriteVerbose("Culture: " + fileculture); WriteVerbose("Token : " + filetoken); var query = new QueryExpression("pluginassembly"); query.ColumnSet.AddColumns("name", "version", "ismanaged"); query.Criteria.AddCondition("name", Microsoft.Xrm.Sdk.Query.ConditionOperator.Equal, filename); query.Criteria.AddCondition("version", Microsoft.Xrm.Sdk.Query.ConditionOperator.Like, fileversion.ToString(2) + "%"); query.Criteria.AddCondition("culture", Microsoft.Xrm.Sdk.Query.ConditionOperator.Equal, fileculture); query.Criteria.AddCondition("publickeytoken", Microsoft.Xrm.Sdk.Query.ConditionOperator.Equal, filetoken); var plugin = CintDynEntity.RetrieveMultiple(container, query).FirstOrDefault(); if (plugin != null) { WriteObject($"Found plugin: {plugin} {plugin.Property("version", "?")}"); if (plugin.Property("ismanaged", false)) { if (!UpdateManaged) { throw new ArgumentOutOfRangeException("AssemblyFile", AssemblyFile, "Assembly is managed in target CRM. Use parameter UpdateManaged to allow this."); } else { WriteWarning("Updating managed assembly"); } } return(plugin); } else { throw new ArgumentOutOfRangeException("AssemblyFile", AssemblyFile, "Assembly does not appear to be registered in CRM"); } }
private CintDynEntity GetAndVerifySolutionForExport(string name) { var cSolutions = CintDynEntity.RetrieveMultiple(crmsvc, "solution", new string[] { "isvisible", "uniquename" }, new object[] { true, name }, new ColumnSet("solutionid", "friendlyname", "version", "ismanaged"), log); if (cSolutions.Count == 0) { throw new ArgumentOutOfRangeException("SolutionUniqueName", name, "Cannot find solution"); } if (cSolutions.Count > 1) { throw new ArgumentOutOfRangeException("SolutionUniqueName", name, "Found " + cSolutions.Count.ToString() + " matching solutions"); } var cdSolution = cSolutions[0]; return(cdSolution); }
private static string GetEntityDisplayString(DataBlockImportMatch match, CintDynEntity cdEntity) { var unique = new List <string>(); if (match != null && match.Attribute.Length > 0) { foreach (var attribute in match.Attribute) { var matchdisplay = attribute.Display; if (string.IsNullOrEmpty(matchdisplay)) { matchdisplay = attribute.Name; } var matchvalue = "<null>"; if (cdEntity.Contains(matchdisplay, true)) { if (cdEntity.Entity[matchdisplay] is EntityReference) { // Don't use PropertyAsString, that would perform GetRelated that we don't want due to performance var entref = cdEntity.Property <EntityReference>(matchdisplay, null); if (!string.IsNullOrEmpty(entref.Name)) { matchvalue = entref.Name; } else { matchvalue = entref.LogicalName + ":" + entref.Id.ToString(); } } else { matchvalue = cdEntity.PropertyAsString(matchdisplay, "", false, false, true); } } unique.Add(matchvalue); } } if (unique.Count == 0) { unique.Add(cdEntity.Id.ToString()); } return(string.Join(", ", unique)); }
private static string GetEntityDisplayString(XmlNode xMatch, CintDynEntity cdEntity) { var unique = new List <string>(); if (xMatch != null && xMatch.ChildNodes.Count > 0) { foreach (XmlNode xMatchAttr in xMatch.ChildNodes) { string matchdisplay = CintXML.GetAttribute(xMatchAttr, "Display"); if (string.IsNullOrEmpty(matchdisplay)) { matchdisplay = CintXML.GetAttribute(xMatchAttr, "Name"); } var matchvalue = "<null>"; if (cdEntity.Contains(matchdisplay, true)) { if (cdEntity.Entity[matchdisplay] is EntityReference) { // Don't use PropertyAsString, that would perform GetRelated that we don't want due to performance var entref = cdEntity.Property <EntityReference>(matchdisplay, null); if (!string.IsNullOrEmpty(entref.Name)) { matchvalue = entref.Name; } else { matchvalue = entref.LogicalName + ":" + entref.Id.ToString(); } } else { matchvalue = cdEntity.PropertyAsString(matchdisplay, "", false, false, true); } } unique.Add(matchvalue); } } if (unique.Count == 0) { unique.Add(cdEntity.Id.ToString()); } return(string.Join(", ", unique)); }
/// <summary> /// Updates the provided web resource /// </summary> /// <param name="script">Web resource to update</param> internal static void UpdateWebResource(this CintContainer container, CintDynEntity wr) { try { var script = wr; if (!script.Contains("webresourceid")) { var existingEntity = container.RetrieveWebResource(script.Property("name", "")); if (existingEntity == null) { script.Id = container.CreateWebResource(script); } else { script.Id = existingEntity.Id; if (!script.Contains("displayname") && existingEntity.Contains("displayname")) { script.AddProperty("displayname", existingEntity.Property("displayname", "")); } if (!script.Contains("description") && existingEntity.Contains("description")) { script.AddProperty("description", existingEntity.Property("description", "")); } script.Save(); } } else { script.Save(); } } catch (Exception error) { throw new Exception("Error while updating web resource: " + error.Message); } }
private static void ReplaceUpdateInfo(CintDynEntity cdEntity) { List <string> removeAttr = new List <string>(); List <KeyValuePair <string, object> > newAttr = new List <KeyValuePair <string, object> >(); foreach (KeyValuePair <string, object> attr in cdEntity.Attributes) { if (attr.Key == "createdby") { if (!cdEntity.Attributes.Contains("createdonbehalfby")) { newAttr.Add(new KeyValuePair <string, object>("createdonbehalfby", attr.Value)); } removeAttr.Add("createdby"); } else if (attr.Key == "modifiedby") { if (!cdEntity.Attributes.Contains("modifiedonbehalfby")) { newAttr.Add(new KeyValuePair <string, object>("modifiedonbehalfby", attr.Value)); } removeAttr.Add("modifiedby"); } else if (attr.Key == "createdon") { if (!cdEntity.Attributes.Contains("overriddencreatedon")) { newAttr.Add(new KeyValuePair <string, object>("overriddencreatedon", attr.Value)); } removeAttr.Add("createdon"); } } foreach (string key in removeAttr) { cdEntity.Attributes.Remove(key); } if (newAttr.Count > 0) { cdEntity.Attributes.AddRange(newAttr); } }
private void ReplaceGuids(CintDynEntity cdEntity, bool includeid) { foreach (KeyValuePair <string, object> prop in cdEntity.Attributes) { if (prop.Value is Guid && guidmap.ContainsKey((Guid)prop.Value)) { if (includeid) { throw new NotImplementedException("Cannot handle replacement of Guid type attributes"); } else { log.Log("No action, we don't care about the guid of the object"); } } if (prop.Value is EntityReference && guidmap.ContainsKey(((EntityReference)prop.Value).Id)) { ((EntityReference)prop.Value).Id = guidmap[((EntityReference)prop.Value).Id]; } } }
private void GetSolutions() { if (Service == null) { return; } if (working) { return; } working = true; WorkAsync(new WorkAsyncInfo("Loading solutions", (eventargs) => { var svc = new CrmServiceProxy(Service); var log = new PluginLogger("ShuffleBuilder", true, ""); try { solutionsUnmanaged = CintDynEntity.RetrieveMultiple(svc, "solution", new string[] { "isvisible", "ismanaged" }, new object[] { true, false }, new ColumnSet("solutionid", "uniquename", "friendlyname", "version"), log); } finally { log.CloseLog(); } }) { PostWorkCallBack = (completedargs) => { if (completedargs.Error != null) { MessageBox.Show(completedargs.Error.Message); } working = false; } }); }
/// <summary> /// Retrieves a specific web resource from its unique name /// </summary> /// <param name="name">Web resource unique name</param> /// <returns>Web resource</returns> internal static CintDynEntity RetrieveWebResource(this CintContainer container, string name) { try { var qba = new QueryByAttribute("webresource"); qba.Attributes.Add("name"); qba.Values.Add(name); qba.ColumnSet = new ColumnSet(true); var collection = CintDynEntity.RetrieveMultiple(container, qba); if (collection.Count > 1) { throw new Exception(string.Format("there are more than one web resource with name '{0}'", name)); } return(collection.FirstOrDefault()); } catch (Exception error) { throw new Exception("Error while retrieving web resource: " + error.Message); } }
private static bool EntityAttributesEqual(List <string> matchattributes, CintDynEntity entity1, CintDynEntity entity2) { var match = true; foreach (var attr in matchattributes) { var srcvalue = ""; if (attr == entity1.PrimaryIdAttribute) { srcvalue = entity1.Id.ToString(); } else { srcvalue = entity1.PropertyAsBaseType(attr, "<null>", false, false, true).ToString(); } var trgvalue = entity2.PropertyAsBaseType(attr, "<null>", false, false, true).ToString(); if (srcvalue != trgvalue) { match = false; break; } } return(match); }
private void SetNewSolutionVersion(string setversion, CintDynEntity cdSolution, Version currentversion) { Version newversion; if (setversion.Equals("IncrementAll", StringComparison.OrdinalIgnoreCase)) { newversion = new Version("1.0.0.0"); foreach (var existingversion in ExistingSolutionVersions.Values) { if (existingversion > newversion) { newversion = existingversion; } } newversion = IncrementVersion(newversion); } else if (setversion.Equals("Increment", StringComparison.OrdinalIgnoreCase)) { newversion = IncrementVersion(currentversion); } else if (setversion.Equals("Current", StringComparison.OrdinalIgnoreCase)) { newversion = currentversion; } else { newversion = new Version(setversion); } if (!currentversion.Equals(newversion)) { SendLine("Setting version: {0}", newversion); var cdSolUpd = cdSolution.Clone(true); cdSolUpd.AddProperty("version", newversion.ToString()); cdSolUpd.Save(); } }
private Tuple <int, int, int, int, int, EntityReferenceCollection> ImportDataBlock(DataBlock block, CintDynEntityCollection cEntities) { log.StartSection("ImportDataBlock"); var created = 0; var updated = 0; var skipped = 0; var deleted = 0; var failed = 0; var references = new EntityReferenceCollection(); var name = block.Name; log.Log("Block: {0}", name); SendStatus(name, null); SendLine(); if (block.Import != null) { var includeid = block.Import.CreateWithId; var save = block.Import.Save; var delete = block.Import.Delete; var updateinactive = block.Import.UpdateInactive; var updateidentical = block.Import.UpdateIdentical; if (block.Import.OverwriteSpecified) { SendLine("DEPRECATED use of attribute Overwrite!"); save = block.Import.Overwrite ? SaveTypes.CreateUpdate : SaveTypes.CreateOnly; } var matchattributes = GetMatchAttributes(block.Import.Match); var updateattributes = !updateidentical?GetUpdateAttributes(cEntities) : new List <string>(); var preretrieveall = block.Import.Match?.PreRetrieveAll == true; SendLine(); SendLine("Importing block {0} - {1} records ", name, cEntities.Count); var i = 1; if (delete == DeleteTypes.All && (matchattributes.Count == 0)) { // All records shall be deleted, no match attribute defined, so just get all and delete all var entity = block.Entity; var qDelete = new QueryExpression(entity); qDelete.ColumnSet.AddColumn(crmsvc.PrimaryAttribute(entity, log)); var deleterecords = CintDynEntity.RetrieveMultiple(crmsvc, qDelete, log); SendLine("Deleting ALL {0} - {1} records", entity, deleterecords.Count); foreach (var record in deleterecords) { SendLine("{0:000} Deleting existing: {1}", i, record); try { record.Delete(); deleted++; } catch (FaultException <OrganizationServiceFault> ex) { if (ex.Message.ToUpperInvariant().Contains("DOES NOT EXIST")) { // This may happen through delayed cascade delete in CRM SendLine(" ...already deleted"); } else { throw; } } i++; } } var totalRecords = cEntities.Count; i = 1; CintDynEntityCollection cAllRecordsToMatch = null; foreach (var cdEntity in cEntities) { var unique = cdEntity.Id.ToString(); SendStatus(-1, -1, totalRecords, i); try { var oldid = cdEntity.Id; var newid = Guid.Empty; ReplaceGuids(cdEntity, includeid); ReplaceUpdateInfo(cdEntity); unique = GetEntityDisplayString(block.Import.Match, cdEntity); SendStatus(null, unique); if (!block.TypeSpecified || block.Type == EntityTypes.Entity) { #region Entity if (matchattributes.Count == 0) { if (save == SaveTypes.Never || save == SaveTypes.UpdateOnly) { skipped++; SendLine("{0:000} Not saving: {1}", i, unique); } else { if (!includeid) { cdEntity.Id = Guid.Empty; } if (SaveEntity(cdEntity, null, updateinactive, updateidentical, i, unique)) { created++; newid = cdEntity.Id; references.Add(cdEntity.Entity.ToEntityReference()); } } } else { var matches = GetMatchingRecords(cdEntity, matchattributes, updateattributes, preretrieveall, ref cAllRecordsToMatch); if (delete == DeleteTypes.All || (matches.Count == 1 && delete == DeleteTypes.Existing)) { foreach (var cdMatch in matches) { SendLine("{0:000} Deleting existing: {1}", i, unique); try { cdMatch.Delete(); deleted++; } catch (FaultException <OrganizationServiceFault> ex) { if (ex.Message.ToUpperInvariant().Contains("DOES NOT EXIST")) { // This may happen through cascade delete in CRM SendLine(" ...already deleted"); } else { throw; } } } matches.Clear(); } if (matches.Count == 0) { if (save == SaveTypes.Never || save == SaveTypes.UpdateOnly) { skipped++; SendLine("{0:000} Not creating: {1}", i, unique); } else { if (!includeid) { cdEntity.Id = Guid.Empty; } if (SaveEntity(cdEntity, null, updateinactive, updateidentical, i, unique)) { created++; newid = cdEntity.Id; references.Add(cdEntity.Entity.ToEntityReference()); } } } else if (matches.Count == 1) { var match = matches[0]; newid = match.Id; if (save == SaveTypes.CreateUpdate || save == SaveTypes.UpdateOnly) { if (SaveEntity(cdEntity, match, updateinactive, updateidentical, i, unique)) { updated++; references.Add(cdEntity.Entity.ToEntityReference()); } else { skipped++; } } else { skipped++; SendLine("{0:000} Exists: {1}", i, unique); } } else { failed++; SendLine("Import object matches {0} records in target database!", matches.Count); SendLine(unique); } } if (!oldid.Equals(Guid.Empty) && !newid.Equals(Guid.Empty) && !oldid.Equals(newid) && !guidmap.ContainsKey(oldid)) { log.Log("Mapping IDs: {0} ==> {1}", oldid, newid); guidmap.Add(oldid, newid); } #endregion Entity } else if (block.Type == EntityTypes.Intersect) { #region Intersect if (cdEntity.Attributes.Count != 2) { throw new ArgumentOutOfRangeException("Attributes", cdEntity.Attributes.Count, "Invalid Attribute count for intersect object"); } var intersect = block.IntersectName; if (string.IsNullOrEmpty(intersect)) { intersect = cdEntity.Name; } var ref1 = (EntityReference)cdEntity.Attributes.ElementAt(0).Value; var ref2 = (EntityReference)cdEntity.Attributes.ElementAt(1).Value; var party1 = CintDynEntity.InitFromNameAndId(ref1.LogicalName, ref1.Id, crmsvc, log); var party2 = CintDynEntity.InitFromNameAndId(ref2.LogicalName, ref2.Id, crmsvc, log); try { party1.Associate(party2, intersect); created++; SendLine("{0} Associated: {1}", i.ToString().PadLeft(3, '0'), name); } catch (Exception ex) { if (ex.Message.Contains("duplicate")) { SendLine("{0} Association exists: {1}", i.ToString().PadLeft(3, '0'), name); skipped++; } else { throw; } } #endregion Intersect } } catch (Exception ex) { failed++; SendLine("\n*** Error record: {0} ***\n{1}", unique, ex.Message); log.Log(ex); if (stoponerror) { throw; } } i++; } SendLine("Created: {0} Updated: {1} Skipped: {2} Deleted: {3} Failed: {4}", created, updated, skipped, deleted, failed); } log.EndSection(); return(new Tuple <int, int, int, int, int, EntityReferenceCollection>(created, updated, skipped, deleted, failed, references)); }
private CintDynEntityCollection ExportDataBlock(ShuffleBlocks blocks, DataBlock block) { log.StartSection("ExportDataBlock"); log.Log("Block: {0}", block.Name); CintDynEntityCollection cExportEntities = null; if (block.Export != null) { #region Define attributes var attributes = block.Export.Items.Where(i => i is DataBlockExportAttributes).FirstOrDefault() as DataBlockExportAttributes; var allcolumns = false; var lAttributes = new List <string>(); var lNullAttributes = new List <string>(); if (attributes != null) { foreach (var attribute in attributes.Attribute) { var attr = attribute.Name; log.Log("Adding column: {0}", attr); lAttributes.Add(attr.Replace("*", "%")); if (attr.Contains("*")) { allcolumns = true; log.Log("Found wildcard"); } else { if (attribute.IncludeNull) { lNullAttributes.Add(attr); } } } } else { allcolumns = true; lAttributes.Add("*"); log.Log("Attributes not specified, retrieving all"); } #endregion Define attributes var fetchxml = block.Export.Items.Where(i => i is string).FirstOrDefault() as string; if (!string.IsNullOrWhiteSpace(fetchxml)) { log.StartSection("Export entity using FetchXML"); #if DEBUG log.Log("FetchXML:\n{0}", fetchxml); #endif cExportEntities = CintDynEntity.RetrieveMultiple(crmsvc, new FetchExpression(fetchxml), log); log.EndSection(); } else if (!block.TypeSpecified || block.Type == EntityTypes.Entity) { #region QueryExpression Entity log.StartSection("Export entity " + block.Entity); var qExport = new QueryExpression(block.Entity); if (block.Export.ActiveOnly) { CintQryExp.AppendConditionActive(qExport.Criteria); } if (block.Relation != null) { foreach (var relation in block.Relation) { AddRelationFilter(blocks, block.Entity, relation, qExport.Criteria, log); } } foreach (var filter in block.Export.Items.Where(i => i is DataBlockExportFilter).Cast <DataBlockExportFilter>()) { AddFilter(qExport, filter); } foreach (var sort in block.Export.Items.Where(i => i is DataBlockExportSort).Cast <DataBlockExportSort>()) { qExport.AddOrder(sort.Attribute, sort.Type == SortTypes.Desc ? OrderType.Descending : OrderType.Ascending); } if (allcolumns) { qExport.ColumnSet = new ColumnSet(true); } else { foreach (var attr in lAttributes) { qExport.ColumnSet.AddColumn(attr); } } #if DEBUG log.Log("Converting to FetchXML"); try { var fetch = CintQryExp.ConvertToFetchXml(qExport, crmsvc); log.Log("Exporting {0}:\n{1}", block.Entity, fetch); } catch (Exception ex) { log.Log("Conversion error:"); log.Log(ex); } #endif cExportEntities = CintDynEntity.RetrieveMultiple(crmsvc, qExport, log); if (allcolumns) { SelectAttributes(cExportEntities, lAttributes, lNullAttributes); } SendLine("Block {0} - {1} records", block.Name, cExportEntities.Count); log.EndSection(); #endregion QueryExpression Entity } else if (block.Type == EntityTypes.Intersect) { #region FetchXML Intersect log.StartSection("Export intersect " + block.Entity); var xDoc = new XmlDocument(); var xEntity = CintFetchXML.Create(xDoc, block.Entity); CintFetchXML.AddAttribute(xEntity, lAttributes.ToArray()); if (block.Relation != null) { foreach (var relation in block.Relation) { AddRelationFilter(blocks, relation, xEntity, log); } } var fetch = xDoc.OuterXml; fetch = fetch.Replace("<fetch ", "<fetch {0} {1} "); // Detta för att se till att CrmServiceProxy.RetrieveMultiple kan hantera paging #if DEBUG log.Log("Exporting intersect entity {0}\n{1}", block.Entity, fetch); #endif var qExport = new FetchExpression(fetch); cExportEntities = CintDynEntity.RetrieveMultiple(crmsvc, qExport, log); foreach (var cde in cExportEntities) { var newattributes = new List <KeyValuePair <string, object> >(); foreach (var attr in cde.Attributes) { if (attr.Value is Guid) { var attrname = attr.Key; var relatedentity = attrname.Substring(0, attrname.Length - (attrname.EndsWith("idone") || attrname.EndsWith("idtwo") ? 5 : 2)); newattributes.Add(new KeyValuePair <string, object>(attrname, new EntityReference(relatedentity, (Guid)attr.Value))); } } foreach (var newattr in newattributes) { if (!newattr.Key.Equals(cde.PrimaryIdAttribute)) { cde.AddProperty(newattr.Key, newattr.Value); } } } log.EndSection(); #endregion FetchXML Intersect } log.Log("Returning {0} records", cExportEntities.Count); } log.EndSection(); return(cExportEntities); }
public static void PublishDuplicateRule(this CintDynEntity duplicateRule) => duplicateRule.Container.Service.Execute(new PublishDuplicateRuleRequest { DuplicateRuleId = duplicateRule.Id });
private CintDynEntityCollection ExportDataBlock(ShuffleBlocks blocks, XmlNode xBlock) { log.StartSection("ExportDataBlock"); string name = CintXML.GetAttribute(xBlock, "Name"); log.Log("Block: {0}", name); CintDynEntityCollection cExportEntities = null; if (xBlock.Name != "DataBlock") { throw new ArgumentOutOfRangeException("Type", xBlock.Name, "Invalid Block type"); } string entity = CintXML.GetAttribute(xBlock, "Entity"); string type = CintXML.GetAttribute(xBlock, "Type"); XmlNode xExport = CintXML.FindChild(xBlock, "Export"); if (xExport != null) { if (string.IsNullOrEmpty(entity)) { entity = CintXML.GetAttribute(xExport, "Entity"); } #region Define attributes XmlNode xAttributes = CintXML.FindChild(xExport, "Attributes"); bool allcolumns = false; List <string> lAttributes = new List <string>(); List <string> lNullAttributes = new List <string>(); if (xAttributes != null) { foreach (XmlNode xAttr in xAttributes.ChildNodes) { if (xAttr.Name == "Attribute") { string attr = CintXML.GetAttribute(xAttr, "Name"); log.Log("Adding column: {0}", attr); lAttributes.Add(attr.Replace("*", "%")); if (attr.Contains("*")) { allcolumns = true; log.Log("Found wildcard"); } else { bool includenull = CintXML.GetBoolAttribute(xAttr, "IncludeNull", false); if (includenull) { lNullAttributes.Add(attr); } } } } } else { allcolumns = true; lAttributes.Add("*"); log.Log("Attributes not specified, retrieving all"); } #endregion Define attributes if (type == "Entity" || string.IsNullOrEmpty(type)) { #region QueryExpression Entity log.StartSection("Export entity " + entity); QueryExpression qExport = new QueryExpression(entity); if (CintXML.GetBoolAttribute(xExport, "ActiveOnly", true)) { CintQryExp.AppendConditionActive(qExport.Criteria); } foreach (var xBlockChild in xBlock.ChildNodes.Cast <XmlNode>()) { if (xBlockChild.Name == "Relation") { AddRelationFilter(blocks, xBlockChild, qExport.Criteria, log); } } foreach (XmlNode xExpProp in xExport.ChildNodes) { if (xExport.NodeType == XmlNodeType.Element) { switch (xExpProp.Name) { case "#comment": case "Attributes": break; case "Filter": AddFilter(qExport, xExpProp); break; case "Sort": qExport.AddOrder( CintXML.GetAttribute(xExpProp, "Attribute"), CintXML.GetAttribute(xExpProp, "Type") == "Desc" ? OrderType.Descending : OrderType.Ascending); break; default: throw new ArgumentOutOfRangeException("Name", xExpProp.Name, "Invalid subitem to export block " + name); } } } if (allcolumns) { qExport.ColumnSet = new ColumnSet(true); } else { foreach (string attr in lAttributes) { qExport.ColumnSet.AddColumn(attr); } } #if DEBUG log.Log("Converting to FetchXML"); try { var fetch = CintQryExp.ConvertToFetchXml(qExport, crmsvc); log.Log("Exporting {0}:\n{1}", entity, fetch); } catch (Exception ex) { log.Log("Conversion error:"); log.Log(ex); } #endif cExportEntities = CintDynEntity.RetrieveMultiple(crmsvc, qExport, log); if (allcolumns) { SelectAttributes(cExportEntities, lAttributes, lNullAttributes); } SendLine("Block {0} - {1} records", name, cExportEntities.Count); log.EndSection(); #endregion QueryExpression Entity } else if (type == "Intersect") { #region FetchXML Intersect log.StartSection("Export intersect " + entity); XmlDocument xDoc = new XmlDocument(); XmlNode xEntity = CintFetchXML.Create(xDoc, entity); CintFetchXML.AddAttribute(xEntity, lAttributes.ToArray()); foreach (var xBlockChild in xBlock.ChildNodes.Cast <XmlNode>()) { if (xBlockChild.Name == "Relation") { AddRelationFilter(blocks, xBlockChild, xEntity, log); } } var fetch = xDoc.OuterXml; fetch = fetch.Replace("<fetch ", "<fetch {0} {1} "); // Detta för att se till att CrmServiceProxy.RetrieveMultiple kan hantera paging #if DEBUG log.Log("Exporting intersect entity {0}\n{1}", entity, fetch); #endif var qExport = new FetchExpression(fetch); cExportEntities = CintDynEntity.RetrieveMultiple(crmsvc, qExport, log); foreach (var cde in cExportEntities) { List <KeyValuePair <string, object> > newattributes = new List <KeyValuePair <string, object> >(); foreach (var attr in cde.Attributes) { if (attr.Value is Guid) { var attrname = attr.Key; string relatedentity = attrname.Substring(0, attrname.Length - (attrname.EndsWith("idone") || attrname.EndsWith("idtwo") ? 5 : 2)); newattributes.Add(new KeyValuePair <string, object>(attrname, new EntityReference(relatedentity, (Guid)attr.Value))); } } foreach (var newattr in newattributes) { if (!newattr.Key.Equals(cde.PrimaryIdAttribute)) { cde.AddProperty(newattr.Key, newattr.Value); } } } log.EndSection(); #endregion FetchXML Intersect } log.Log("Returning {0} records", cExportEntities.Count); } log.EndSection(); return(cExportEntities); }
private CintDynEntityCollection GetMatchingRecordsFromPreRetrieved(List <string> matchattributes, CintDynEntity cdEntity, CintDynEntityCollection cAllRecordsToMatch) { log.StartSection(MethodBase.GetCurrentMethod().Name); log.Log("Searching matches for: {0} {1}", cdEntity.Id, cdEntity); var result = new CintDynEntityCollection(); foreach (var cdRecord in cAllRecordsToMatch) { if (EntityAttributesEqual(matchattributes, cdEntity, cdRecord)) { result.Add(cdRecord); log.Log("Found match: {0} {1}", cdRecord.Id, cdRecord); } } log.Log("Returned matches: {0}", result.Count); log.EndSection(); return(result); }
private void ExportSolutionBlock(XmlNode xBlock) { log.StartSection("ExportSolutionBlock"); if (xBlock.Name != "SolutionBlock") { throw new ArgumentOutOfRangeException("Type", xBlock.Name, "Invalid Block type"); } string name = CintXML.GetAttribute(xBlock, "Name"); log.Log("Block: {0}", name); string path = CintXML.GetAttribute(xBlock, "Path"); string file = CintXML.GetAttribute(xBlock, "File"); if (string.IsNullOrWhiteSpace(path) && !string.IsNullOrWhiteSpace(definitionpath)) { path = definitionpath; path += path.EndsWith("\\") ? "" : "\\"; } if (string.IsNullOrWhiteSpace(file)) { file = name; } XmlNode xExport = CintXML.FindChild(xBlock, "Export"); if (xExport != null) { string type = CintXML.GetAttribute(xExport, "Type"); string setversion = CintXML.GetAttribute(xExport, "SetVersion"); bool publish = CintXML.GetBoolAttribute(xExport, "PublishBeforeExport", false); string targetversion = CintXML.GetAttribute(xExport, "TargetVersion"); CintDynEntity cdSolution = GetAndVerifySolutionForExport(name); var currentversion = new Version(cdSolution.Property("version", "1.0.0.0")); SendLine("Solution: {0} {1}", name, currentversion); if (!string.IsNullOrWhiteSpace(setversion)) { SetNewSolutionVersion(setversion, cdSolution, currentversion); } if (publish) { SendLine("Publishing customizations"); crmsvc.Execute(new PublishAllXmlRequest()); } ExportSolutionRequest req = new ExportSolutionRequest() { SolutionName = name }; #if Crm8 if (!string.IsNullOrWhiteSpace(targetversion)) { req.TargetVersion = targetversion; } #endif XmlNode xSettings = CintXML.FindChild(xExport, "Settings"); if (xSettings != null) { req.ExportAutoNumberingSettings = CintXML.GetBoolAttribute(xSettings, "AutoNumbering", false); req.ExportCalendarSettings = CintXML.GetBoolAttribute(xSettings, "Calendar", false); req.ExportCustomizationSettings = CintXML.GetBoolAttribute(xSettings, "Customization", false); req.ExportEmailTrackingSettings = CintXML.GetBoolAttribute(xSettings, "EmailTracking", false); req.ExportGeneralSettings = CintXML.GetBoolAttribute(xSettings, "General", false); req.ExportMarketingSettings = CintXML.GetBoolAttribute(xSettings, "Marketing", false); req.ExportOutlookSynchronizationSettings = CintXML.GetBoolAttribute(xSettings, "OutlookSync", false); req.ExportRelationshipRoles = CintXML.GetBoolAttribute(xSettings, "RelationshipRoles", false); req.ExportIsvConfig = CintXML.GetBoolAttribute(xSettings, "IsvConfig", false); } if (type == "Managed" || type == "Both") { string filename = path + file + "_managed.zip"; SendLine("Exporting solution to: {0}", filename); req.Managed = true; ExportSolutionResponse exportSolutionResponse = (ExportSolutionResponse)crmsvc.Execute(req); byte[] exportXml = exportSolutionResponse.ExportSolutionFile; File.WriteAllBytes(filename, exportXml); } if (type == "Unmanaged" || type == "Both") { string filename = path + file + ".zip"; SendLine("Exporting solution to: {0}", filename); req.Managed = false; ExportSolutionResponse exportSolutionResponse = (ExportSolutionResponse)crmsvc.Execute(req); byte[] exportXml = exportSolutionResponse.ExportSolutionFile; File.WriteAllBytes(filename, exportXml); } } log.EndSection(); }
/// <summary> /// Retrieves all web resources that are customizable /// </summary> /// <returns>List of web resources</returns> internal static CintDynEntityCollection RetrieveWebResources(this CintContainer container, Guid solutionId, List <int> types, bool hideMicrosoftWebresources) { try { if (solutionId == Guid.Empty) { var qe = new QueryExpression("webresource") { ColumnSet = new ColumnSet(true), Criteria = new FilterExpression { Filters = { new FilterExpression { FilterOperator = LogicalOperator.And, Conditions = { new ConditionExpression("ishidden", ConditionOperator.Equal, false), } }, new FilterExpression { FilterOperator = LogicalOperator.Or, Conditions = { new ConditionExpression("ismanaged", ConditionOperator.Equal, false), new ConditionExpression("iscustomizable", ConditionOperator.Equal, true), } } } }, Orders = { new OrderExpression("name", OrderType.Ascending) } }; if (hideMicrosoftWebresources) { qe.Criteria.Filters.First().Conditions.AddRange( new ConditionExpression("name", ConditionOperator.DoesNotBeginWith, "cc_MscrmControls"), new ConditionExpression("name", ConditionOperator.DoesNotBeginWith, "msdyn_") ); } if (types.Count != 0) { qe.Criteria.Filters.First().Conditions.Add(new ConditionExpression("webresourcetype", ConditionOperator.In, types.ToArray())); } return(CintDynEntity.RetrieveMultiple(container, qe)); } else { var qba = new QueryByAttribute("solutioncomponent") { ColumnSet = new ColumnSet(true) }; qba.Attributes.AddRange(new[] { "solutionid", "componenttype" }); qba.Values.AddRange(new object[] { solutionId, 61 }); var components = CintDynEntity.RetrieveMultiple(container, qba); var list = components.Select(component => component.Property("objectid", Guid.Empty).ToString("B")) .ToList(); if (list.Count > 0) { var qe = new QueryExpression("webresource") { ColumnSet = new ColumnSet(true), Criteria = new FilterExpression { Filters = { new FilterExpression { FilterOperator = LogicalOperator.And, Conditions = { new ConditionExpression("ishidden", ConditionOperator.Equal, false), new ConditionExpression("webresourceid", ConditionOperator.In, list.ToArray()), } }, new FilterExpression { FilterOperator = LogicalOperator.Or, Conditions = { new ConditionExpression("ismanaged", ConditionOperator.Equal, false), new ConditionExpression("iscustomizable", ConditionOperator.Equal, true), } } } }, Orders = { new OrderExpression("name", OrderType.Ascending) } }; if (types.Count != 0) { qe.Criteria.Filters.First().Conditions.Add(new ConditionExpression("webresourcetype", ConditionOperator.In, types.ToArray())); } return(CintDynEntity.RetrieveMultiple(container, qe)); } return(new CintDynEntityCollection()); } } catch (Exception error) { throw new Exception("Error while retrieving web resources: " + error.Message); } }
private bool DoImportSolutionAsync(ImportSolutionRequest impSolReq, ref Exception ex) { log.StartSection(MethodBase.GetCurrentMethod().Name); // Code cred to Wael Hamze // http://waelhamze.com/2013/11/17/asynchronous-solution-import-dynamics-crm-2013/ var result = false; var asyncRequest = new ExecuteAsyncRequest() { Request = impSolReq }; var asyncResponse = crmsvc.Execute(asyncRequest) as ExecuteAsyncResponse; var asyncJobId = asyncResponse.AsyncJobId; var end = DateTime.MaxValue; var importStatus = -1; var progress = 0; var statustext = "Submitting job"; SendLineUpdate("Import status: {0}", statustext); while (end >= DateTime.Now) { CintDynEntity cdAsyncOperation = null; try { cdAsyncOperation = CintDynEntity.Retrieve(SystemJob.EntityName, asyncJobId, new ColumnSet(SystemJob.PrimaryKey, SystemJob.Status, SystemJob.StatusReason, SystemJob.Message, SystemJob.Friendlymessage), crmsvc, log); } catch (Exception asyncex) { cdAsyncOperation = null; log.Log(asyncex); log.EndSection(); // Ending section started by Retrieve above to prevent indentation inflation } if (cdAsyncOperation != null) { statustext = cdAsyncOperation.PropertyAsString(SystemJob.StatusReason, "?", false, false); var newStatus = cdAsyncOperation.Property(SystemJob.StatusReason, new OptionSetValue()).Value; if (newStatus != importStatus) { importStatus = newStatus; if (end.Equals(DateTime.MaxValue) && importStatus != (int)SystemJob.StatusReason_OptionSet.Waiting) { end = timeout > 0 ? DateTime.Now.AddMinutes(timeout) : DateTime.Now.AddMinutes(2); SendLineUpdate("Import job picked up at {0}", DateTime.Now); log.Log("Timout until: {0}", end.ToString("HH:mm:ss.fff")); SendLine("Import status: {0}", statustext); } SendLineUpdate("Import status: {0}", statustext); log.Log("Import message:\n{0}", cdAsyncOperation.Property(SystemJob.Message, "<none>")); if (importStatus == (int)SystemJob.StatusReason_OptionSet.Succeeded) { // Succeeded result = true; break; } else if (importStatus == (int)SystemJob.StatusReason_OptionSet.Pausing || importStatus == (int)SystemJob.StatusReason_OptionSet.Canceling || importStatus == (int)SystemJob.StatusReason_OptionSet.Failed || importStatus == (int)SystemJob.StatusReason_OptionSet.Canceled) { // Error statuses var friendlymessage = cdAsyncOperation.Property(SystemJob.Friendlymessage, ""); SendLine("Message: {0}", friendlymessage); if (friendlymessage == "Access is denied.") { SendLine("When importing to onprem environment, the async service user must be granted read/write permission to folder:"); SendLine(" C:\\Program Files\\Microsoft Dynamics CRM\\CustomizationImport"); } else { var message = cdAsyncOperation.Property(SystemJob.Message, "<none>"); message = ExtractErrorMessage(message); if (!string.IsNullOrWhiteSpace(message) && !message.Equals(friendlymessage, StringComparison.InvariantCultureIgnoreCase)) { SendLine("Detailed message: \n{0}", message); } else { SendLine("See log file for technical details."); } } ex = new Exception(string.Format("Solution Import Failed: {0} - {1}", cdAsyncOperation.PropertyAsString(SystemJob.Status, "?", false, false), cdAsyncOperation.PropertyAsString(SystemJob.StatusReason, "?", false, false))); break; } } } System.Threading.Thread.Sleep(1000); if (importStatus == 20) { // In progress, read percent try { var job = CintDynEntity.Retrieve(ImportJob.EntityName, impSolReq.ImportJobId, new ColumnSet(ImportJob.Progress), crmsvc, log); if (job != null) { var newProgress = Convert.ToInt32(Math.Round(job.Property(ImportJob.Progress, 0D))); if (newProgress > progress) { progress = newProgress; SendStatus(-1, -1, 100, progress); SendLineUpdate("Import status: {0} - {1}%", statustext, progress); } } } catch (Exception jobex) { // We probably tried before the job was created if (jobex.Message.ToUpperInvariant().Contains("DOES NOT EXIST")) { log.Log("Importjob not created yet or already deleted"); } else { log.Log(jobex); } log.EndSection(); // Ending section started by Retrieve above to prevent indentation inflation } } } if (end < DateTime.Now) { SendLine("Import timed out."); } SendStatus(-1, -1, 100, 0); log.EndSection(); return(result); }
private Tuple <int, int, int, int, int, EntityReferenceCollection> ImportDataBlock(XmlNode xBlock, CintDynEntityCollection cEntities) { log.StartSection("ImportDataBlock"); int created = 0; int updated = 0; int skipped = 0; int deleted = 0; int failed = 0; EntityReferenceCollection references = new EntityReferenceCollection(); string name = CintXML.GetAttribute(xBlock, "Name"); log.Log("Block: {0}", name); SendStatus(name, null); SendLine(); switch (xBlock.Name) { case "DataBlock": string type = CintXML.GetAttribute(xBlock, "Type"); XmlNode xImport = CintXML.FindChild(xBlock, "Import"); if (xImport != null) { var includeid = CintXML.GetBoolAttribute(xImport, "CreateWithId", false); var save = CintXML.GetAttribute(xImport, "Save"); var delete = CintXML.GetAttribute(xImport, "Delete"); var updateinactive = CintXML.GetBoolAttribute(xImport, "UpdateInactive", false); var updateidentical = CintXML.GetBoolAttribute(xImport, "UpdateIdentical", false); var deprecatedoverwrite = CintXML.GetAttribute(xImport, "Overwrite"); if (!string.IsNullOrWhiteSpace(deprecatedoverwrite)) { SendLine("DEPRECATED use of attribute Overwrite!"); bool overwrite = CintXML.GetBoolAttribute(xImport, "Overwrite", true); save = overwrite ? "CreateUpdate" : "CreateOnly"; } if (string.IsNullOrWhiteSpace(save)) { // Default save = "CreateUpdate"; } if (string.IsNullOrWhiteSpace(delete)) { // Default delete = "None"; } XmlNode xMatch = CintXML.FindChild(xImport, "Match"); var matchattributes = GetMatchAttributes(xMatch); var updateattributes = !updateidentical?GetUpdateAttributes(cEntities) : new List <string>(); var preretrieveall = xMatch != null?CintXML.GetBoolAttribute(xMatch, "PreRetrieveAll", false) : false; SendLine(); SendLine("Importing block {0} - {1} records ", name, cEntities.Count); var i = 1; if (delete == "All" && (matchattributes.Count == 0)) { // All records shall be deleted, no match attribute defined, so just get all and delete all string entity = CintXML.GetAttribute(xBlock, "Entity"); var qDelete = new QueryExpression(entity); qDelete.ColumnSet.AddColumn(crmsvc.PrimaryAttribute(entity, log)); var deleterecords = CintDynEntity.RetrieveMultiple(crmsvc, qDelete, log); SendLine("Deleting ALL {0} - {1} records", entity, deleterecords.Count); foreach (var record in deleterecords) { SendLine("{0:000} Deleting existing: {1}", i, record); try { record.Delete(); deleted++; } catch (FaultException <OrganizationServiceFault> ex) { if (ex.Message.ToUpperInvariant().Contains("DOES NOT EXIST")) { // This may happen through delayed cascade delete in CRM SendLine(" ...already deleted"); } else { throw; } } i++; } } int totalRecords = cEntities.Count; i = 1; CintDynEntityCollection cAllRecordsToMatch = null; foreach (CintDynEntity cdEntity in cEntities) { string unique = cdEntity.Id.ToString(); SendStatus(-1, -1, totalRecords, i); try { Guid oldid = cdEntity.Id; Guid newid = Guid.Empty; ReplaceGuids(cdEntity, includeid); ReplaceUpdateInfo(cdEntity); unique = GetEntityDisplayString(xMatch, cdEntity); SendStatus(null, unique); if (type == "Entity" || string.IsNullOrEmpty(type)) { #region Entity if (matchattributes.Count == 0) { if (save == "Never" || save == "UpdateOnly") { skipped++; SendLine("{0:000} Not saving: {1}", i, unique); } else { if (!includeid) { cdEntity.Id = Guid.Empty; } if (SaveEntity(cdEntity, null, updateinactive, updateidentical, i, unique)) { created++; newid = cdEntity.Id; references.Add(cdEntity.Entity.ToEntityReference()); } } } else { var matches = GetMatchingRecords(cdEntity, matchattributes, updateattributes, preretrieveall, ref cAllRecordsToMatch); if (delete == "All" || (matches.Count == 1 && delete == "Existing")) { foreach (CintDynEntity cdMatch in matches) { SendLine("{0:000} Deleting existing: {1}", i, unique); try { cdMatch.Delete(); deleted++; } catch (FaultException <OrganizationServiceFault> ex) { if (ex.Message.ToUpperInvariant().Contains("DOES NOT EXIST")) { // This may happen through cascade delete in CRM SendLine(" ...already deleted"); } else { throw; } } } matches.Clear(); } if (matches.Count == 0) { if (save == "Never" || save == "UpdateOnly") { skipped++; SendLine("{0:000} Not creating: {1}", i, unique); } else { if (!includeid) { cdEntity.Id = Guid.Empty; } if (SaveEntity(cdEntity, null, updateinactive, updateidentical, i, unique)) { created++; newid = cdEntity.Id; references.Add(cdEntity.Entity.ToEntityReference()); } } } else if (matches.Count == 1) { var match = matches[0]; newid = match.Id; if (save == "CreateUpdate" || save == "UpdateOnly") { if (SaveEntity(cdEntity, match, updateinactive, updateidentical, i, unique)) { updated++; references.Add(cdEntity.Entity.ToEntityReference()); } else { skipped++; } } else { skipped++; SendLine("{0:000} Exists: {1}", i, unique); } } else { failed++; SendLine("Import object matches {0} records in target database!", matches.Count); SendLine(unique); } } if (!oldid.Equals(Guid.Empty) && !newid.Equals(Guid.Empty) && !oldid.Equals(newid) && !guidmap.ContainsKey(oldid)) { log.Log("Mapping IDs: {0} ==> {1}", oldid, newid); guidmap.Add(oldid, newid); } #endregion Entity } else if (type == "Intersect") { #region Intersect if (cdEntity.Attributes.Count != 2) { throw new ArgumentOutOfRangeException("Attributes", cdEntity.Attributes.Count, "Invalid Attribute count for intersect object"); } string intersect = CintXML.GetAttribute(xBlock, "IntersectName"); if (string.IsNullOrEmpty(intersect)) { intersect = cdEntity.Name; } EntityReference ref1 = (EntityReference)cdEntity.Attributes.ElementAt(0).Value; EntityReference ref2 = (EntityReference)cdEntity.Attributes.ElementAt(1).Value; CintDynEntity party1 = CintDynEntity.InitFromNameAndId(ref1.LogicalName, ref1.Id, crmsvc, log); CintDynEntity party2 = CintDynEntity.InitFromNameAndId(ref2.LogicalName, ref2.Id, crmsvc, log); try { party1.Associate(party2, intersect); created++; SendLine("{0} Associated: {1}", i.ToString().PadLeft(3, '0'), name); } catch (Exception ex) { if (ex.Message.Contains("duplicate")) { SendLine("{0} Association exists: {1}", i.ToString().PadLeft(3, '0'), name); skipped++; } else { throw; } } #endregion Intersect } } catch (Exception ex) { failed++; SendLine("\n*** Error record: {0} ***\n{1}", unique, ex.Message); log.Log(ex); if (stoponerror) { throw; } } i++; } SendLine("Created: {0} Updated: {1} Skipped: {2} Deleted: {3} Failed: {4}", created, updated, skipped, deleted, failed); } break; default: throw new ArgumentOutOfRangeException("Type", xBlock.Name, "Invalid Block type"); } log.EndSection(); return(new Tuple <int, int, int, int, int, EntityReferenceCollection>(created, updated, skipped, deleted, failed, references)); }
private bool SaveEntity(CintDynEntity cdNewEntity, CintDynEntity cdMatchEntity, bool updateInactiveRecord, bool updateIdentical, int pos, string identifier) { log.StartSection("SaveEntity " + pos.ToString("000 ") + identifier); bool recordSaved = false; if (string.IsNullOrWhiteSpace(identifier)) { identifier = cdNewEntity.ToString(); } var newOwner = cdNewEntity.Property <EntityReference>("ownerid", null); var newState = cdNewEntity.Property <OptionSetValue>("statecode", null); var newStatus = cdNewEntity.Property <OptionSetValue>("statuscode", null); var newActive = newState != null?CintEntity.GetActiveStates(cdNewEntity.Name).Contains(newState.Value) : true; bool nowActive = true; if ((newState == null) != (newStatus == null)) { throw new InvalidDataException("When setting status of the record, both statecode and statuscode must be present"); } if (!newActive) { log.Log("Removing state+status from entity to update"); cdNewEntity.RemoveProperty("statecode"); cdNewEntity.RemoveProperty("statuscode"); } if (cdMatchEntity == null) { cdNewEntity.Create(); recordSaved = true; SendLine("{0:000} Created: {1}", pos, identifier); } else { var oldState = cdMatchEntity.Property <OptionSetValue>("statecode", null); var oldActive = oldState != null?CintEntity.GetActiveStates(cdNewEntity.Name).Contains(oldState.Value) : true; nowActive = oldActive; cdNewEntity.Id = cdMatchEntity.Id; if (!oldActive && (newActive || updateInactiveRecord)) { // Inaktiv post som ska aktiveras eller uppdateras cdNewEntity.SetState(0, 1); SendLine("{0:000} Activated: {1} for update", pos, identifier); nowActive = true; } if (nowActive) { var updateattributes = cdNewEntity.Attributes.Keys.ToList(); if (updateattributes.Contains(cdNewEntity.PrimaryIdAttribute)) { updateattributes.Remove(cdNewEntity.PrimaryIdAttribute); } if (updateIdentical || !EntityAttributesEqual(updateattributes, cdNewEntity, cdMatchEntity)) { cdNewEntity.Update(); recordSaved = true; SendLine("{0:000} Updated: {1}", pos, identifier); } else { SendLine("{0:000} Skipped: {1} (Identical)", pos, identifier); } } else { SendLine("{0:000} Inactive: {1}", pos, identifier); } if (newOwner != null && !newOwner.Equals(cdMatchEntity.Property("ownerid", new EntityReference()))) { cdNewEntity.Assign(newOwner); SendLine("{0:000} Assigned: {1} to {2} {3}", pos, identifier, newOwner.LogicalName, string.IsNullOrEmpty(newOwner.Name) ? newOwner.Id.ToString() : newOwner.Name); } } if (newActive != nowActive) { // Aktiv skall ändras på posten var newStatusValue = newStatus.Value; if (cdNewEntity.Name == "savedquery" && newState.Value == 1 && newStatusValue == 1) { // Justering för inaktiverad men ej publicerad vy newStatusValue = 2; } cdNewEntity.SetState(newState.Value, newStatusValue); SendLine("{0:000} SetState: {1}: {2}/{3}", pos, identifier, newState.Value, newStatus.Value); } log.EndSection(); return(recordSaved); }