Thursday, 30 July 2009

Some undocumented CRM attribute types

I was working on some custom plugin registration tools recently, and came across some undocumented attribute types. Several customisation entities (e.g. PluginAssembly, PluginType, SavedQuery) have an attribute called CustomizationLevel which has a value of 0 for system data, and 1 if it is custom or customised (according to the SDK).

The SDK documentation states this attribute is of type CrmNumber, so when writing a QueryExpression that selects only records with a CustomizationLevel = 1, it would seem reasonable to use something like:

qe.Criteria.AddCondition(new ConditionExpression("customizationlevel", ConditionOperator.Equal, 1));

However, this gives the error “Condition for attribute 'customizationlevel': expected argument(s) of type 'System.Byte' but received 'System.Int32' " (code 0x80040203 - Invalid Argument). Digging deeper I found that the field for the CustomizationLevel is stored in SQL as a tinyint (i.e. a single-byte integer), and that the AttributeTypes table in CRM has a corresponding AttributeType of tinyint.

So, despite the attribute being identified as a CrmNumber, any condition expressions need to pass values as a single-byte integer, not the documented four-byte integer. This is easily done by using the following:

qe.Criteria.AddCondition(new ConditionExpression("customizationlevel", ConditionOperator.Equal, (Byte) 1));

Being somewhat nosey, I thought to see what other attribute types there were. These can be easily found with the following SQL query:

Select * from AttributeTypes

In addition to tinyint, 2 similar types caught my attention – smallint and bigint (SQL Server data type names are not that imaginative). Following on from this, the following SQL query lists attributes of these types, which may cause similar problems to those above:

select e.name as Entity, a.name as Attribute, at.description as [Type]
from attribute a join entity e on a.entityid = e.entityid
join attributetypes at on a.attributetypeid = at.attributetypeid
where at.description in ('tinyint', 'smallint', 'bigint')
order by at.description, e.name, a.name

This yields the following results. The bigint attributes aren’t a concern, as these 2 attributes aren’t available via the CRM platform, but you could encounter some of the smallint types on UserSettings, in which case I expect you’d have to cast values to Int16.

EntityAttributeType
AsyncOperationsequencebigint
Subscriptioncompletedsyncversionnumberbigint
Organizationtokenexpirysmallint
UserSettingsadvancedfindstartupmodesmallint
UserSettingstimezonecodesmallint
UserSettingstimezonedaylightdaysmallint
UserSettingstimezonedaylightdayofweeksmallint
UserSettingstimezonedaylighthoursmallint
UserSettingstimezonedaylightminutesmallint
UserSettingstimezonedaylightmonthsmallint
UserSettingstimezonedaylightsecondsmallint
UserSettingstimezonedaylightyearsmallint
UserSettingstimezonestandarddaysmallint
UserSettingstimezonestandarddayofweeksmallint
UserSettingstimezonestandardhoursmallint
UserSettingstimezonestandardminutesmallint
UserSettingstimezonestandardmonthsmallint
UserSettingstimezonestandardsecondsmallint
UserSettingstimezonestandardyearsmallint
Organizationfiscalyeardisplaycodetinyint
Organizationtagmaxaggressivecyclestinyint
Organizationtrackingtokeniddigitstinyint
OrganizationUIcustomizationleveltinyint
PluginAssemblycustomizationleveltinyint
PluginTypecustomizationleveltinyint
SavedQuerycustomizationleveltinyint
SdkMessagecustomizationleveltinyint
SdkMessageFiltercustomizationleveltinyint
SdkMessagePaircustomizationleveltinyint
SdkMessageProcessingStepcustomizationleveltinyint
SdkMessageProcessingStepImagecustomizationleveltinyint
SdkMessageProcessingStepSecureConfigcustomizationleveltinyint
SdkMessageRequestcustomizationleveltinyint
SdkMessageRequestFieldcustomizationleveltinyint
SdkMessageRequestInputcustomizationleveltinyint
SdkMessageResponsecustomizationleveltinyint
SdkMessageResponseFieldcustomizationleveltinyint

Thursday, 23 July 2009

Reading RDL Definitions directly from a ReportServer database

Just a quick post: I recently had to extract the report definitions (RDL) directly from a ReportServer database, as the ReprtServer installation was broken. This should be straightforward, but requires some work to convert the data to a readable format. This can be done with the following SQL query:

select convert(varchar(max), convert(varbinary(max), content))
from catalog
where content is not null

Sunday, 5 July 2009

MS Dynamics Top 100 Influential People

Sometimes it's good to come last. I was honoured and flattered to find my name at no. 100 (that's me, last on the list) in “The Microsoft Dynamics Top 100 Influential People 2009" at DynamicsWorld.


It's good to see several other CRM MVPs ahead of me on the list - you can find out who they are here

Friday, 3 July 2009

CRM 4 Update Rollup 5

As several others have announced, CRM 4 Update Rollup 5 has been released. There are a couple of notable points to make:

  1. As with update rollups 3 and 4, the majority of the fixes have not been previously released as an individual hotfix. This is different from rollups 1 and 2, which were mostly a collection of previously released fixes. In general, I think that having fewer individually released fixes is a positive thing, but that has to be traded off against the frequency of rollups (currently about every 6 to 8 weeks), which is difficult to keep up with. Across our customers, we have deployments covering 5 different rollup levels, plus some customers on CRM 3, which needs a fair bit of management, especially with regard to schema compatibility
  2. So, schema compatibility. Apparently, UR5 schemas cannot be imported into versions prior to UR2, but also, pre-UR2 schemas cannot be imported into UR5. I've got some investigation to do on this, but the most important factor for me is being able to use one development environment that can be used to export (and import if necessary) schemas to all rollup versions of CRM 4. Up to now I've rarely applied rollups to development environments, but it looks like from now on, UR2 will be a minimum requirement for a development environment. Either way, it makes life harder than it should be.