A friend and former co-worker of mine, Jake Ginnivan forwarded a thread to me started by Darrell Tunnell to the DbUp mailing list. DbUp is a .NET API for building database migration tooling for applications by sequentially applying update scripts to a database, and keeping track of which scripts have been applied.
Darrell’s thread mentioned that he was working at a derivative work which could be used to apply changes to Dynamics CRM, he has called his tool CrmUp. For those of you who haven’t used Dynamics CRM before, out of the box it provides a way for businesses to manage sales, service and marketing processes.
Dynamics CRM is interesting from a development perspective because it is all built upon a customisable foundation where you can build your own custom business entities, relate them together and build processes that flow across the top of them complete with dashboarding and reporting. For some classes of problems it is a very productive development environment.
The product bundles customisations together into things called “Solutions” which contain the definition of all the customisations to be applied and this allows developers to ship grouped customisations to target environments. CrmUp is useful because it allows Dynamics CRM to be treated like an application dependency that can be upgraded to a baseline version.
Darrell’s work has got me thinking about what I would want from a developer orientated framework for managing customisations to Dynamics CRM. If we look at databases generally there are three broad approaches:
- Model/Tooling Driven Migrations (e.g. Database Projects in Visual Studio)
- Script Driven Migrations (e.g. *.sql scripts applied sequentially)
- Code Driven Migrations (e.g. EF CodeFirst)
Dynamics CRM doesn’t have a project type in CRM. The development environment is really CRM itself, from which you can export you customisations. It is these exported customisations (solution files) which are then fed into CrmUp.
Personally I am a huge fan of the way that Entity Framework Code-First migrations work. I love the fact that I can define my database entities in code, and add behaviour to them and then use the tooling to build a “migration” which takes me from one version of the database schema to the other. This leads me to wonder what a Code-First CRM framework would look like.
Dynamics CRM has various customisable elements:
- Entities (create new, and extend existing)
- Processes, Workflows & Workflow Activities
- Forms (for Entities)
- Service Endpoints
- … and many more.
This is perhaps what makes the CrmUp approach somewhat easier to get off the ground (because you are leveraging existing solution/customisation files). But in the long run a code-based way of defining the above would be incredibly useful.
For example, it would be great if I could define an entity in code:
[Entity(Name = “CustomEntity”)]
public class CustomEntityDefinition: EntityDefinition
public override void Retrieve(RetrieveContext context)
// Do whatever.
Having this entity definition as part of a deployment would result in an entity being created, but a plug-in would also be generated which would route traffic to an Azure host (in the Dynamics Online scenario) to invoke the Retrieve method whenever that entity is retrieved.
There would be additional base classes and associated attributes to describe all aspects of a CRM solution in-code, and then you could do something similar to “Enable-Migrations” from Entity Framework to create the migration scaffolding. As the code is updated you could call “Add-Migrations” and it would generate a migration between the earlier migration and the current state. It would also take into consideration publisher details/signing and versioning.
I personally think that Dynamics CRM is an awesome product, and I’ve been working with it for years, but I would really love to have a more streamlined developer experience. Hat’s off to Darrell Tunnell for his contribution. I hope that the Dynamics team looks at what he has done and also looks at how the Entity Framework project has approached the challenge.