When writing plugin code CRM has a very frustrating feature which allows it’s fields to be null. Note I said this was a feature not a bug 🙂
I believe this was was one of the main reasons in CRM 4 it had it’s own set of variables CrmDateTime, CrmDecimal, CrmFloat, CrmMoney, CrmNumber. These could hold a null as well as value (I think, it has been a while since I did any CRM 4 development).
Where this really niggles me is when I can’t pass anearly bound field into a method because the method takes a bool but the early bound field is a ?bool, which basically means it’s a bool that can be null.
So how do we code around this
Late bound
So in previous blog post I have talked about using Entity.GetAttributeValue instead of Entity.Contains
using GetAttributeValue is great because it means I could take all the entity.contains code below
if (entity.Contains("salutation")) { title = ( string)entity.Attributes["salutation"]; }
The GetAttributeValue returns either a null or a default value. This is great for bools, ints etc because instead of null I now get false or 0;
Type | Return |
Numerical (int, decimal, double) | 0 |
Boolean | false |
DateTime | DateTime.MinValue |
Guid | Guid.Empty |
For other variables it will return a null.
Early bound
What if you are using early bound classes and don’t want to add the potential risk of putting in syntax errors in your plugin code by using late bound code.
What are the benefits of early bound code
- Readability
- No Syntax errors at runtime
- casting errors are found at compile time
- Easier to read, debug, maintain and extend
The main reason I like early bound classes is because it’s easier to understand and I don’t have to keep looking up and typing the name of the CRM fields. It also moves most of the errors into compile time (syntax and casting errors), which means it’s less likely these errors will get through to the customers.
GetValueOrDefault to the rescue
If you want to convert the an early bound field into simple attribute then you should use GetValueOrDefault, which
The reason it’s a good idea to use this is because if you casted it to a bool or int you are in danger of creating an error because you cannot set a bool to be null!
The GetValueOrDefault will return a value (the default value for the variable type) even when the HasValue for the field is false (e.g. it’s null). Using the GetValueOrDefault means you don’t catch the error but you do have to be prepared for receiving a default value and code with that in mind.
So here it is in action
if (entity.Contains("salutation")) bool credit = entity. CreditOnHold.GetValueOrDefault (); entity. CreditOnHold = true ; credit = entity. CreditOnHold.GetValueOrDefault ();
The MSDN article if you want more, to be honest there isn’t much more to say about it.