This article is the third in a series I am writing on the inner-workings of the Notifications Accelerator for Microsoft Dynamics CRM. The first two parts of the series focused on the Installer and ISV.config and the Subscription Chooser Page. If you have not yet checked those articles out, it would be a good idea to do so before diving in and reading this one. Today, I’m going to discuss the Metadata Cache object in the accelerator.
First off, I’m not going to try and claim credit for creating the CrmMetadataCache class in the solution. It is largely untouched from the previous version originally written by Michaeljon Miller. He did a great job with this and pretty much the only tweaks I added were the use of the CrmHelper class in a couple of areas and also updating some lines to allow the cache to show user localized labels. Read his post on the 3.0 version of the code (heck, download it and take a peek, even!) and you’ll likely find out about some of the quirks in the 4.0 version.
Structure
Let’s start off with the building blocks of the cache. We have two class objects that represent the basic info we store in the cache, CrmMetadataAttribute and CrmMetadataEntity. We’ll spend a few minutes to take a look at these objects.
CrmMetadataAttribute
This object is intended, obviously, to represent the attributes in an entity. There are three properties that we want to capture for each attribute:
- DisplayName – Specifies the attribute’s display name in CRM.
- SchemaName – Specifies the attribute’s actual schema name.
- Type – Indicates which type of CRM attribute is the attribute (string, money, picklist, etc).
CrmMetadataEntity
The CrmMetadataEntity is where the exciting stuff starts happening. This object contains all sorts of data related to an entity in CRM. The properties of the CrmMetadataEntity are as follows:
- DisplayName – Specifies the display name of the entity.
- SchemaName – Specifies the schema name of the entity.
- ObjectTypeCode – Specifies the entity’s object type code.
- PrimaryKeyAttribute – Indicates which attribute is the primary key.
- PrimaryDisplayAttribute – Indicates which attribute is the primary display attribute.
- IsCustomEntity – Indicates whether the entity is a custom entity.
- Attributes – A hash table containing a collection of all of the attributes for the entity. This collection contains the CrmMetadataAttribute object for each attribute.
There is one function in the class, GetAttribute(), which returns the CrmMetadataAttribute object when given an attribute’s schema name.
This brings us to the CrmMetadataCache.
CrmMetadataCache
The operations going on in the cache are pretty simple. In the class constructor, we call the CacheMetadata method – which calls the CRM Metadata Service to retrieve a list of all entities and their attributes:
static void CacheMetadata()
{
// Build metadata cache
oHelper = new CrmHelper();
MetadataService.MetadataService oMetadataService = oHelper.oMetadataService;
RetrieveAllEntitiesRequest oRequest = new RetrieveAllEntitiesRequest();
oRequest.RetrieveAsIfPublished = true;
oRequest.MetadataItems = MetadataItems.IncludeAttributes;
RetrieveAllEntitiesResponse oResponse = (RetrieveAllEntitiesResponse)oMetadataService.Execute(oRequest);
foreach (EntityMetadata oEntity in oResponse.CrmMetadata)
{
if (oEntity.DisplayName.UserLocLabel != null &&
oEntity.PrimaryField != null &&
oEntity.PrimaryKey != null &&
oEntity.IsCustomizable.Value == true)
{
CrmMetadataEntity localEntity = new CrmMetadataEntity(oEntity);
byName.Add(oEntity.SchemaName.ToLower(), localEntity);
byCode.Add(oEntity.ObjectTypeCode.Value, localEntity);
entityList.Add(oEntity.DisplayName.UserLocLabel.Label, oEntity.SchemaName.ToLower());
}
}
}
Notice we’re using our helper class to grab our service objects. For each entity that is returned by the Metadata Service, we add the entity to two hash tables (byName and byCode). The main functionality of the cache is to return the entity information when the ByName and ByCode methods are called. Also, we put the entity schema and display names into a sorted list.
As you would expect, the cache can take some time when it is being built. The biggest factor in the amount of time needed is obviously the number of customizations you’ve made within CRM. More customizations = more time for the cache to build.
One issue we ran into when updating everything for CRM 4.0 was trying to account for views in CRM that contained attributes from linked entities. The current structure of the cache does not allow for that functionality - that’s one area I would like to see beefed up since I didn’t spend a lot of time doing that.
That all I have for the Metadata Cache. The next article in this series will focus on the actual RSS feed generator.
Technorati tags: Dynamics CRM CRM Accelerator Notifications Accelerator Codeplex CRM RSS
Comments