CRM 2013: Cannot specify child attribute retrieve – MergeRequest C#

Hello!

If you are working on code to merge two entity records and come across “Cannot specify child attribute retrieve” error; and you have referred SDK/MSDN documentation. You probably have kept UpdateContent property optional and havent set it. UpdateContent is a required property though the documentation says it is not.

This property is optional in case of merging incidents only.

You just have to set Entity object to UpdateContent property which has attributes to be updated to the merged record.

Entity contact = new Entity("contact");
contact["firstname"] = "Crm";
contact["lastname"] = "Xpress";
 
// merging contact records
MergeRequest merge = new MergeRequest
{
    // SubordinateId is the GUID of the contact merging.
    SubordinateId = contactId,
    Target = target,
    PerformParentingChecks = true,
    UpdateContent = contact // Entity Object to set the content you want updated on the merged contact
};

HTH!
Happy Merging!

CRM 2011, C#: Entity Class redefined with .net framwork 3.5 to connect CRM 2011

Look at my previous post on connecting CRM 2011 using .net framework 3.5 without CRM 2011 SDK. https://consultrikin.wordpress.com/2013/09/19/crm-2011-c-connect-crm-2011-without-using-sdkusing-net-framework-3-5/

Here, if you use Entity Class to create Entity records the same way we create records in .net framework 4.0 with SDK in late bound; this requires following syntax.

Entity entity = new Entity();
entity.LogicalName = "contact";
entity.Attributes = new ServiceReference1.AttributeCollection();
entity.Attributes.Add(new KeyValuePair<string, object>("firstname", "test first name"));
entity.Attributes.Add(new KeyValuePair<string, object>("lastname", "test last name"));
OrgService.Create(entity);

Here, you must add an attribute value as a new KeyValuePair<string, object>. Or you need to access the attributes by their indexes like:

Entity entity = new Entity();
entity.LogicalName = "contact";
entity.Attributes = new ServiceReference1.AttributeCollection();
entity.Attributes[0] = "test first name";
entity.Attributes[1] = "test last name";
OrgService.Create(entity);

This code does not have readability as you need to find int index every time you access entity. While I found the same extended Entity Class from the posts I mentioned in my previous post. Here they are listed. Just add them to your project and you will be able to add attributes with string parameters.

/// <summary>
/// Entity Class
/// </summary>
partial class Entity
{
	/// <summary>
	/// Initializes a new instance of the <see cref="Entity" /> class.
	/// </summary>
	public Entity()
	{
		this.FormattedValuesField = new FormattedValueCollection();
		this.RelatedEntitiesField = new RelatedEntityCollection();
	}

	/// <summary>
	/// Gets the attribute value.
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="attributeLogicalName">Name of the attribute logical.</param>
	/// <returns></returns>
	public T GetAttributeValue<T>(string attributeLogicalName)
	{
		if (null == this.Attributes)
		{
			this.Attributes = new AttributeCollection();
		};
		object value;
		if (this.Attributes.TryGetValue(attributeLogicalName, out value))
		{
			return (T)value;
		}

		return default(T);
	}

	/// <summary>
	/// Gets or sets the <see cref="System.Object"/> with the specified attribute name.
	/// </summary>
	/// <value>
	/// The <see cref="System.Object"/>.
	/// </value>
	/// <param name="attributeName">Name of the attribute.</param>
	/// <returns></returns>
	public object this[string attributeName]
	{
		get
		{
			if (null == this.Attributes)
			{
				this.Attributes = new AttributeCollection();
			};

			return this.Attributes.GetItem(attributeName);
		}
		set
		{
			if (null == this.Attributes)
			{
				this.Attributes = new AttributeCollection();
			};

			this.Attributes.SetItem(attributeName, value);
		}
	}
}

And Add following Class-

/// <summary>
/// CollectionExtensions Class
/// </summary>
public static class CollectionExtensions
{
	/// <summary>
	/// Gets the item.
	/// </summary>
	/// <typeparam name="TKey">The type of the key.</typeparam>
	/// <typeparam name="TValue">The type of the value.</typeparam>
	/// <param name="collection">The collection.</param>
	/// <param name="key">The key.</param>
	/// <returns>returns TValue</returns>
	/// <exception cref="System.Collections.Generic.KeyNotFoundException">Key =  + key</exception>
	public static TValue GetItem<TKey, TValue>(this IList<KeyValuePair<TKey, TValue>> collection, TKey key)
	{
		TValue value;
		if (TryGetValue(collection, key, out value))
		{
			return value;
		}

		throw new System.Collections.Generic.KeyNotFoundException("Key = " + key);
	}

	/// <summary>
	/// Sets the item.
	/// </summary>
	/// <typeparam name="TKey">The type of the key.</typeparam>
	/// <typeparam name="TValue">The type of the value.</typeparam>
	/// <param name="collection">The collection.</param>
	/// <param name="key">The key.</param>
	/// <param name="value">The value.</param>
	public static void SetItem<TKey, TValue>(this IList<KeyValuePair<TKey, TValue>> collection, TKey key, TValue value)
	{
		int index;

		if (TryGetIndex<TKey, TValue>(collection, key, out index))
		{
			collection.RemoveAt(index);
		}

		//If the value is an array, it needs to be converted into a List. This is due to how Silverlight serializes
		//Arrays and IList<T> objects (they are both serialized with the same namespace). Any collection objects will
		//already add the KnownType for IList<T>, which means that any parameters that are arrays cannot be added
		//as a KnownType (or it will throw an exception).
		Array array = value as Array;
		if (null != array)
		{
			Type listType = typeof(List<>).GetGenericTypeDefinition().MakeGenericType(array.GetType().GetElementType());
			object list = Activator.CreateInstance(listType, array);
			try
			{
				value = (TValue)list;
			}
			catch (InvalidCastException)
			{
				//Don't do the conversion because the types are not compatible
			}
		}

		collection.Add(new KeyValuePair<TKey, TValue>(key, value));
	}

	/// <summary>
	/// Determines whether the specified collection contains key.
	/// </summary>
	/// <typeparam name="TKey">The type of the key.</typeparam>
	/// <typeparam name="TValue">The type of the value.</typeparam>
	/// <param name="collection">The collection.</param>
	/// <param name="key">The key.</param>
	/// <returns>returns true or false</returns>
	public static bool ContainsKey<TKey, TValue>(this IList<KeyValuePair<TKey, TValue>> collection, TKey key)
	{
		int index;
		return TryGetIndex<TKey, TValue>(collection, key, out index);
	}

	/// <summary>
	/// Tries the get value.
	/// </summary>
	/// <typeparam name="TKey">The type of the key.</typeparam>
	/// <typeparam name="TValue">The type of the value.</typeparam>
	/// <param name="collection">The collection.</param>
	/// <param name="key">The key.</param>
	/// <param name="value">The value.</param>
	/// <returns>returns true or false</returns>
	public static bool TryGetValue<TKey, TValue>(this IList<KeyValuePair<TKey, TValue>> collection, TKey key, out TValue value)
	{
		int index;
		if (TryGetIndex<TKey, TValue>(collection, key, out index))
		{
			value = collection[index].Value;
			return true;
		}

		value = default(TValue);
		return false;
	}

	/// <summary>
	/// Tries the index of the get.
	/// </summary>
	/// <typeparam name="TKey">The type of the key.</typeparam>
	/// <typeparam name="TValue">The type of the value.</typeparam>
	/// <param name="collection">The collection.</param>
	/// <param name="key">The key.</param>
	/// <param name="index">The index.</param>
	/// <returns>returns true or false</returns>
	private static bool TryGetIndex<TKey, TValue>(IList<KeyValuePair<TKey, TValue>> collection, TKey key, out int index)
	{
		if (null == collection || null == key)
		{
			index = -1;
			return false;
		}

		index = -1;
		for (int i = 0; i < collection.Count; i++)
		{
			if (key.Equals(collection[i].Key))
			{
				index = i;
				return true;
			}
		}

		return false;
	}
}

Happy Programming!!