Previously, I used to access the value of a property like entity["attributename"] and cast the result into the appropriate type. The preceding line to this, would always be a check to see if the property exists, as it can cause a KeyNotFoundException, without this check. GetAttributeValue is how I access attribute values these days. These are some influential posts that made me change my behaviour.
David Berry -> http://crmentropy.blogspot.com.au/2013/08/entitygetattributevalue-explained.html
Guido Preite -> http://www.crmanswers.net/2014/09/getattributevalue-activityparty.html
While this does prevent KeyNotFoundException, it is important to understand the behaviour of GetAttributeValue, w.r.t DateTime. When GetAttributeValue is invoked to retrieve a DateTime attribute, and the value of the attribute is null, it returns a DateTime.MinValue, which is 01/01/0001.
In a scenario where a retrieved value is used to update another record, you'll have to check if this is DateTime.MinValue before updating, or it will cause an exception like the one below.
The exception thrown is "DateTime is less than minumum[sic] value supported by CrmDateTime. Actual value: 01/01/0001 11:00:00, Minimum value supported: 01/01/1900 00:00:00". To prevent this exception, I check if the retrieved DateTime value == DateTime.MinValue, and if so, choose not to update the target property, or set it as null, depending on the requirement. It is also a realisation for me, that CrmDateTime still lives on, somewhere in the Sdk assemblies.
EDIT (29/01/15): Following David's tip from the comment below, the better approach is to use nullable types with GetAttributeValue, so I should be using DateTime? instead of DateTime.
David Berry -> http://crmentropy.blogspot.com.au/2013/08/entitygetattributevalue-explained.html
Guido Preite -> http://www.crmanswers.net/2014/09/getattributevalue-activityparty.html
While this does prevent KeyNotFoundException, it is important to understand the behaviour of GetAttributeValue, w.r.t DateTime. When GetAttributeValue is invoked to retrieve a DateTime attribute, and the value of the attribute is null, it returns a DateTime.MinValue, which is 01/01/0001.
In a scenario where a retrieved value is used to update another record, you'll have to check if this is DateTime.MinValue before updating, or it will cause an exception like the one below.
The exception thrown is "DateTime is less than minumum[sic] value supported by CrmDateTime. Actual value: 01/01/0001 11:00:00, Minimum value supported: 01/01/1900 00:00:00". To prevent this exception, I check if the retrieved DateTime value == DateTime.MinValue, and if so, choose not to update the target property, or set it as null, depending on the requirement. It is also a realisation for me, that CrmDateTime still lives on, somewhere in the Sdk assemblies.
EDIT (29/01/15): Following David's tip from the comment below, the better approach is to use nullable types with GetAttributeValue, so I should be using DateTime? instead of DateTime.
If you use Entity.GetAttributeValue, you'll be given a null value, rather than DateTime.Min. It may be easier to handle. :)
ReplyDeleteI did use GetAttributeValue. I noticed that it returned DateTime.Min when 1.) The attribute is in the columnset and it's value is null 2.) When a datetime attribute is not mentioned in the columnset e.g. modifiedon. Please check the result of this code snippet.
ReplyDeletevar contact = crmSvc.OrganizationServiceProxy.RetrieveMultiple(new FetchExpression(@"")).Entities[0];
Console.WriteLine(contact.GetAttributeValue("modifiedon"));
query is this..blogger seems to have stripped out the fetch..
ReplyDelete<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false"><entity name="contact"><attribute name="fullname"/><attribute name="telephone1"/><attribute name="emailaddress1"/><attribute name="mobilephone"/><attribute name="contactid"/><order attribute="fullname" descending="false"/><filter type="and"><condition attribute="statecode" operator="eq" value="0"/></filter></entity></fetch>
Raj, I'm sorry, my comment contained angle brackets that were buried by the HTML. What I meant to write was: Entity.GetAttributeValue<DateTime?>("modifiedon"). Note the cast of the nullable type: DateTime?
ReplyDeleteThis is probably what I should have been doing..Thank you for the tip..
ReplyDelete