/// <summary> /// Gets a <c>QueryExpression</c> instance with it's properties set to the values supplied /// </summary> /// <param name="entityName">The name of the <c>BusinessEntity</c> as a <c>string</c> to be queried</param> /// <param name="modifiedDate">The <c>string</c> value for the date to be queried from</param> /// <param name="adapter">An instance of a <c>CRM2011Adapter</c> used to retrieve the INTEGRATION user's <c>Guid</c></param> /// <param name="isDynamic">True if the object provider calling into this method is a <c>DynamicObbjectProvider</c> and false otherwise</param> /// <param name="columnSet">A CRM <c>ColumnSet</c> that contains the columns to be returned from the query.</param> /// <returns>An instance of a <c>QueryExpression</c> that can used as a parameter to a <c>RetrieveMultipleRequest</c></returns> /// <remarks>The method generates a query that is retrieved by the modified date supplied as well as the IntegrationReady flag and the modified by /// property not being equal to the INTEGRATION user's id</remarks> public static QueryExpression GetReaderQueryExpression(string entityName, DateTime modifiedDate, DynamicCrmAdapter adapter, bool isDynamic, ColumnSet columnSet) { if (adapter == null) { throw new AdapterException(string.Format(CultureInfo.CurrentCulture, Resources.ArgumentNullExceptionMessage), new ArgumentNullException("adapter")) { ExceptionId = AdapterException.SystemExceptionGuid }; } ValidatePropertyQueryParameters(entityName, "modifiedon"); QueryExpression queryHelper = new QueryExpression(entityName) { Distinct = false, Criteria = new FilterExpression(), ColumnSet = columnSet }; queryHelper.ColumnSet.AllColumns = true; if (entityName != null) { if (entityName == "activitymimeattachment") { LinkEntity emailLink = new LinkEntity() { LinkFromEntityName = "activitymimeattachment", LinkFromAttributeName = "activityid", LinkToEntityName = "email", LinkToAttributeName = "activityid", LinkCriteria = { Conditions = { new ConditionExpression( "modifiedon", ConditionOperator.GreaterEqual, modifiedDate) } } }; queryHelper.LinkEntities.Add(emailLink); } else { queryHelper.Criteria.Conditions.Add(new ConditionExpression("modifiedon", ConditionOperator.GreaterEqual, modifiedDate)); } } if (!isDynamic) { queryHelper.Criteria.Conditions.Add(new ConditionExpression(CRM2011AdapterUtilities.DynamicsIntegrationReady, ConditionOperator.Equal, true)); } return queryHelper; }
/// <summary> /// Gets a <c>Picklist</c> instance who's values are set based on the parameters provided. /// </summary> /// <param name="entity">The current <c>Entity</c>.</param> /// <param name="field">The current <c>DefinitionField</c> for the property being mapped to this <c>Picklist</c>.</param> /// <param name="mappedLookupObject">The <c>Dictionary</c> containing the lookup information for the <c>Picklist</c>.</param> /// <param name="crm2011Adapter">The <c>CRM2011Adapter</c> to use when calling the CRM web service.</param> /// <param name="providedEntityName">The name of the <c>Entity</c> that the current object provider is for.</param> /// <returns>A <c>Picklist</c> with it's value property set to the one requested in the <c>Dictionary</c>, if one is found and <c>null</c> otherwise.</returns> /// <exception cref="ArgumentException">Thrown if the requested value is not currently in the <c>Picklist</c> within the CRM system.</exception> public static OptionSetValue MapPicklist(Entity entity, FieldDefinition field, Dictionary<string, object> mappedLookupObject, DynamicCrmAdapter crm2011Adapter, string providedEntityName) { if (entity == null || field == null || crm2011Adapter == null) { throw new AdapterException(string.Format(CultureInfo.CurrentCulture, Resources.ArgumentNullExceptionMessage)) { ExceptionId = AdapterException.SystemExceptionGuid }; } ValidateDictionary(mappedLookupObject); if (!mappedLookupObject.Keys.Contains("Value")) { if (!mappedLookupObject.Keys.Contains("name") || string.IsNullOrEmpty(mappedLookupObject["name"] as string)) { return null; } RetrieveAttributeRequest attribReq = new RetrieveAttributeRequest() { EntityLogicalName = entity.LogicalName, LogicalName = field.Name, RetrieveAsIfPublished = true }; if (IsSpecialAddressPicklist(entity, field)) { attribReq.EntityLogicalName = providedEntityName; attribReq.LogicalName = string.Format(CultureInfo.CurrentCulture, "address{0}_{1}", ((int?)entity["addressnumber"]).Value.ToString(CultureInfo.CurrentCulture), field.Name); } // Get the attribute metadata for the state attribute. RetrieveAttributeResponse metadataResponse = (RetrieveAttributeResponse)crm2011Adapter.OrganizationService.Execute(attribReq); PicklistAttributeMetadata picklistAttrib = (PicklistAttributeMetadata)metadataResponse.AttributeMetadata; var picklistValue = from option in picklistAttrib.OptionSet.Options where option.Label.UserLocalizedLabel.Label.ToUpperInvariant() == mappedLookupObject["name"].ToString().ToUpperInvariant() select option.Value; // ensure that both the returned list and the first item in the returned list are not null or empty. if ((picklistValue.Count() > 0) && (picklistValue.First() != null)) { return new OptionSetValue(picklistValue.First().Value); } throw new AdapterException(string.Format(CultureInfo.CurrentCulture, Resources.PicklistValueNotFound, mappedLookupObject["name"].ToString(), field.DisplayName, entity.LogicalName)) { ExceptionId = ErrorCodes.PicklistMappingNotFound }; } OptionSetValue mapping = new OptionSetValue(); SetRelationshipValuesFromDictionary(mappedLookupObject, mapping); return mapping; }
/// <summary> /// Converts all representations of the state property to an integer. /// </summary> /// <param name="stateName">The state to get the integer value of as a <c>string</c>.</param> /// <param name="entityName">The name of the entity type to get the state code for.</param> /// <param name="adapter">The <see cref="DynamicCrmAdapter"/> to use for calling into a CRM for resolving that state.</param> /// <returns>An <c>int</c> the represents the state.</returns> public static int ConvertStateNameToValue(string stateName, string entityName, DynamicCrmAdapter adapter) { if (adapter == null) { throw new ArgumentNullException("adapter"); } RetrieveAttributeRequest attribReq = new RetrieveAttributeRequest() { EntityLogicalName = entityName, LogicalName = "statecode", RetrieveAsIfPublished = true }; // Get the attribute metadata for the state attribute. RetrieveAttributeResponse metadataResponse = (RetrieveAttributeResponse)adapter.OrganizationService.Execute(attribReq); StateAttributeMetadata picklistAttrib = (StateAttributeMetadata)metadataResponse.AttributeMetadata; var picklistValue = from option in picklistAttrib.OptionSet.Options where option.Label.UserLocalizedLabel.Label.ToUpperInvariant() == stateName.ToUpperInvariant() select option.Value; // Ensure that both the returned list and the first item in the returned list are not null or empty. if ((picklistValue.Count() > 0) && (picklistValue.First() != null)) { return picklistValue.First().Value; } return CRM2011AdapterUtilities.GetDefaultStateCodeValue(stateName); }
/// <summary> /// Gets an instance of the <c>customeraddress</c> class. /// </summary> /// <param name="addressIntegrationKeyValue">The value of the address's dynamics_integrationkey property to query for.</param> /// <param name="parentKey">The parent of this address to use when querying for the existence of this address instance.</param> /// <param name="adapter">An instance of the <c>CRM2011Adapter</c> class to use when calling CRM.</param> /// <param name="addressIntegrationKeyProperty">The key attribute on the <c>customeraddress</c> that the supplied value is for.</param> /// <returns>A new instance with it's dynamics_integrationkey initialized to the value supplied or an existing instance.</returns> public static Entity GetDynamicAddressInstance(string addressIntegrationKeyValue, Guid parentKey, DynamicCrmAdapter adapter, string addressIntegrationKeyProperty) { if (parentKey == null || adapter == null) { throw new AdapterException(string.Format(CultureInfo.CurrentCulture, Resources.ArgumentNullExceptionMessage)) { ExceptionId = AdapterException.SystemExceptionGuid }; } if (string.IsNullOrEmpty(addressIntegrationKeyProperty)) { throw new AdapterException(string.Format(CultureInfo.CurrentCulture, Resources.AddressIntegrationKeyPropertyInvalidMessage)) { ExceptionId = ErrorCodes.AddressIntegrationKeyPropertyException }; } RetrieveMultipleRequest retrieveRequest = new RetrieveMultipleRequest(); KeyValuePair<string, string>[] propertyValues = new KeyValuePair<string, string>[2]; propertyValues[0] = new KeyValuePair<string, string>(addressIntegrationKeyProperty, addressIntegrationKeyValue); propertyValues[1] = new KeyValuePair<string, string>("parentid", parentKey.ToString()); retrieveRequest.Query = CRM2011AdapterUtilities.GetMultipartQueryExpression(LogicalOperator.And, "customeraddress", propertyValues); RetrieveMultipleResponse retrieveResponse = (RetrieveMultipleResponse)adapter.OrganizationService.Execute(retrieveRequest); Entity returnedEntity = null; if (retrieveResponse.EntityCollection.Entities.Count == 1) { returnedEntity = retrieveResponse.EntityCollection.Entities[0] as Entity; returnedEntity[CRM2011AdapterUtilities.IsNew] = false; return returnedEntity; } else if (retrieveResponse.EntityCollection.Entities.Count < 1) { // this is a new entity instance and we need to map the provided data onto the DynamicsEntity returnedEntity = new Entity() { LogicalName = "customeraddress" }; if (addressIntegrationKeyProperty.Equals("customeraddressid", StringComparison.OrdinalIgnoreCase)) { returnedEntity[addressIntegrationKeyProperty] = new Guid(addressIntegrationKeyValue); } else { returnedEntity[addressIntegrationKeyProperty] = addressIntegrationKeyValue; } returnedEntity[CRM2011AdapterUtilities.IsNew] = true; return returnedEntity; } else { throw new AdapterException( string.Format( CultureInfo.CurrentCulture, Resources.MultipleDynamicEntitiesReturnedExceptionMessage, "customeraddress", addressIntegrationKeyProperty, addressIntegrationKeyValue)) { ExceptionId = ErrorCodes.MultipleCustomerAddressResult }; } }
/// <summary> /// Populates the activity party list for a given CRM <c>Entity</c>. /// </summary> /// <param name="dynamicEntity">The CRM <c>Entity</c> to be populated.</param> /// <param name="complexTypeDictionary">The <c>Dictionary</c> that contains the <see cref="ComplexType"/> definition.</param> /// <param name="property">The activity properties on the entity that was supplied.</param> /// <param name="adapter">The <see cref="DynamicCrmAdapter"/> to use to when calling into CRM to get the parties.</param> /// <param name="definition">The <see cref="FieldDefinition"/> that contains the data about the activity field.</param> private static void PopulatePartyList(Entity dynamicEntity, Dictionary<string, object> complexTypeDictionary, KeyValuePair<string, object> property, DynamicCrmAdapter adapter, FieldDefinition definition) { PopulateDictionary(dynamicEntity, complexTypeDictionary, property); var tempDictionary = new Dictionary<string, object>(); foreach (var entity in (DataCollection<Entity>)complexTypeDictionary["Entities"]) { var entityDictionary = GetDictionary(entity, adapter, definition.TypeDefinition.Children.ToList()); var name = entityDictionary["activitypartyid"].ToString(); if (!string.IsNullOrEmpty(name)) { tempDictionary.Add(name, entityDictionary); } } complexTypeDictionary.Add("ActivityParties", tempDictionary); }
/// <summary> /// Gets a <c>Dictionary</c> that represents a <c>DynamicEntity</c>. /// </summary> /// <param name="entity">The CRM <c>Entity</c> to return as a <c>Dictioanry</c>.</param> /// <param name="adapter">An instance of a <c>CRMAdapter</c> to use when getting dynamics_integrationkey data for a <c>Lookup</c> type.</param> /// <param name="fieldDefinitions">The <C>List</C> of <see cref="FieldDefinition"/>s to use when populating the <C>Dictionary</C>.</param> /// <returns>A <c>Dictionary</c> that has Keys that are the property names of the <c>DynamicEntity</c> supplied and /// Values that are the values of those properties on the <c>DynamicEntity</c>.</returns> internal static Dictionary<string, object> GetDictionary(Entity entity, DynamicCrmAdapter adapter, List<FieldDefinition> fieldDefinitions) { Dictionary<string, object> dictionary = new Dictionary<string, object>(); // This dictionary is for holding a complexType that might be the type for the current property on the entity Dictionary<string, object> holdingDictionary; foreach (KeyValuePair<string, object> property in entity.Attributes) { // CrmMoney needs the dictionary to be converted but it also starts with the same prefix as the property types that do not,so handle it separately // else if the property is not one of the Built-in types and is also not of the StringProperty type, use the holding dictionary Type propertyType = property.Value.GetType(); holdingDictionary = new Dictionary<string, object>(); if (propertyType == typeof(Money)) { PopulateDictionary(entity, holdingDictionary, property); } else if (propertyType == typeof(OptionSetValue)) { PopulateOptionSetValueDictionary(entity, holdingDictionary, property, adapter); } else if (propertyType == typeof(EntityReference)) { FieldDefinition definition = fieldDefinitions.FirstOrDefault(x => x.Name == property.Key); PopulateDictionary(entity, holdingDictionary, property, adapter, definition); } else if (propertyType == typeof(EntityCollection)) { FieldDefinition definition = fieldDefinitions.FirstOrDefault(x => x.Name == property.Key); PopulatePartyList(entity, holdingDictionary, property, adapter, definition); } // The property is of a ComplexType and the holding dictionary was populated // else if the property is one of the Built-in CRM types just convert it // else if the property was a string property, just use its value if (holdingDictionary.Count > 0) { dictionary.Add(property.Key, holdingDictionary); } else { dictionary.Add(property.Key, property.Value); } } if (fieldDefinitions.Any(x => x.Name == "overriddencreatedon")) { dictionary.Add("overriddencreatedon", null); } return dictionary; }
/// <summary> /// Populates a <c>Dictionary</c> with the values contained in a <c>DynamicEntity</c>. /// </summary> /// <param name="dynamicEntity">The <c>DynamicEntity</c> to get the properties and data from.</param> /// <param name="complexTypeDictionary">The <c>Dictionary</c> to be populated.</param> /// <param name="property">The property on the <c>DynamicEntity</c> to populate the supplied <c>Dictionary</c> for.</param> /// <param name="adapter">An instance of a <c>CRMAdapter</c> to use when getting dynamics_integrationkey data for a <c>Lookup</c> type.</param> private static void PopulateOptionSetValueDictionary(Entity dynamicEntity, Dictionary<string, object> complexTypeDictionary, KeyValuePair<string, object> property, DynamicCrmAdapter adapter) { PopulateDictionary(dynamicEntity, complexTypeDictionary, property); if (!complexTypeDictionary.ContainsKey("name")) { RetrieveAttributeRequest attribReq = new RetrieveAttributeRequest() { EntityLogicalName = dynamicEntity.LogicalName, LogicalName = property.Key, RetrieveAsIfPublished = true }; // Get the attribute metadata for the state attribute. RetrieveAttributeResponse metadataResponse = (RetrieveAttributeResponse)adapter.OrganizationService.Execute(attribReq); PicklistAttributeMetadata picklistAttrib = metadataResponse.AttributeMetadata as PicklistAttributeMetadata; StateAttributeMetadata stateAttrib = metadataResponse.AttributeMetadata as StateAttributeMetadata; IEnumerable<string> picklistValue = null; if (picklistAttrib != null) { picklistValue = from option in picklistAttrib.OptionSet.Options where option.Value == ((OptionSetValue)property.Value).Value select option.Label.UserLocalizedLabel.Label; } else if (stateAttrib != null) { picklistValue = from option in stateAttrib.OptionSet.Options where option.Value == ((OptionSetValue)property.Value).Value select option.Label.UserLocalizedLabel.Label; } // ensure that both the returned list and the first item in the returned list are not null or empty. if (picklistValue != null && picklistValue.Count() > 0 && picklistValue.First() != null) { complexTypeDictionary.Add("name", picklistValue.First()); } } }
/// <summary> /// Populates a <c>Dictionary</c> with the values contained in a <c>DynamicEntity</c>. /// </summary> /// <param name="dynamicEntity">The <c>DynamicEntity</c> to get the properties and data from.</param> /// <param name="complexTypeDictionary">The <c>Dictionary</c> to be populated.</param> /// <param name="property">The property on the <c>DynamicEntity</c> to populate the supplied <c>Dictionary</c> for.</param> /// <param name="adapter">An instance of a <c>CRMAdapter</c> to use when getting dynamics_integrationkey data for a <c>Lookup</c> type.</param> /// <param name="definition">The <see cref="FieldDefinition"/> for the referenced entity.</param> private static void PopulateDictionary(Entity dynamicEntity, Dictionary<string, object> complexTypeDictionary, KeyValuePair<string, object> property, DynamicCrmAdapter adapter, FieldDefinition definition) { PopulateDictionary(dynamicEntity, complexTypeDictionary, property); if (complexTypeDictionary.ContainsKey("Id") && complexTypeDictionary.ContainsKey("LogicalName")) { if (complexTypeDictionary["LogicalName"].ToString() != "attachment" && complexTypeDictionary["LogicalName"].ToString() != "activitymimeattachment") { ColumnSet cols = new ColumnSet(true); if (!CRM2011AdapterUtilities.GetIntegratedEntities().Contains(complexTypeDictionary["LogicalName"].ToString())) { cols = new ColumnSet(true); } RetrieveRequest request = new RetrieveRequest() { ColumnSet = cols, Target = new EntityReference(complexTypeDictionary["LogicalName"].ToString(), new Guid(complexTypeDictionary["Id"].ToString())) }; RetrieveResponse response = adapter.OrganizationService.Execute(request) as RetrieveResponse; Entity entity = response.Entity; var lookupType = definition.AdditionalAttributes.FirstOrDefault(x => x.Name == "LookupType"); var lookupField = definition.AdditionalAttributes.FirstOrDefault(x => x.Name == "LookupField"); var typeSplit = lookupType.Value.Split(','); var fieldSplit = lookupField.Value.Split(','); var keyValueLookup = new List<KeyValuePair<string, string>>(); if (typeSplit.Count() > 1 && fieldSplit.Count() > 1) { for (int i = 0; i < typeSplit.Count(); i++) { keyValueLookup.Add(new KeyValuePair<string, string>(typeSplit[i], fieldSplit[i])); } lookupField.Value = keyValueLookup.FirstOrDefault(x => x.Key == entity.LogicalName).Value; } if (lookupField != null) { if (lookupField.Value == "domainname" || entity.LogicalName == "systemuser") { lookupField.Value = "fullname"; } else if (entity.LogicalName == "activitypointer") { lookupField.Value = "activityid"; } complexTypeDictionary.Add(lookupField.Value, entity[lookupField.Value]); } } } }
/// <summary> /// Checks if the state of an entity is already properly set and removes it if it is, otherwise it is set. /// </summary> /// <param name="dictionary">The <c>Dictionary</c> that contains the state to be set on the entity.</param> /// <param name="entity">The CRM <c>Entity</c> to set the state on.</param> /// <param name="propertyName">The state code property name.</param> /// <param name="adapter">The <see cref="DynamicCrmAdapter"/> to be used for state name to value conversions.</param> private static void CheckStateAndStatus(Dictionary<string, object> dictionary, Entity entity, string propertyName, DynamicCrmAdapter adapter) { int stateToSet = (int)dictionary[propertyName]; if (!entity.Contains(propertyName) || CRM2011AdapterUtilities.ConvertStateNameToValue(entity[propertyName].ToString(), entity.LogicalName, adapter) != stateToSet) { entity[propertyName] = new OptionSetValue(stateToSet); } else { entity.Attributes.Remove(propertyName); if (entity.Contains("statuscode")) { entity.Attributes.Remove("statuscode"); } } }