Tuesday, July 08, 2008

Importing BRE Vocabulary with Multiple versions

If you ever tried merging all of the versions of a single vocabulary into one XML file, so that you can import it on a single task, you will find that even though the Rules Engine Deployment Wizard understand the file format, it has a huge limitation [Bug..?  ;) ].  It only imports the last version of a vocabulary into the Rules Engine.


A sample vocabulary with 2 versions.


When Exporting this vocabulary I can't export all versions at once.  I have to export a single version at a time.!!

However, on the import, you can import a file that can contain multiple versions on it:


Once you export all individual files, you can merged them into a single xml file.

The format of the merged exported vocabulary will be something like this:

<brl xmlns="http://schemas.microsoft.com/businessruleslanguage/2002">   

  • <vocabulary id="9ab458cc-427a-4cea-bb1d-224dd5f96d98" name="CustomerLevels" uri="" description="">
            <version major="1" minor="1" description="" modifiedby="awing" date="2008-07-07T23:22:33.401-04:00"/>
            <vocabularydefinition id="b36b276e-451d-4783-8a06-623823211f85" name="Silver" description="Silver Description">


  • <vocabulary id="2422362a-77c0-4d0f-b2aa-fe6c1fe1f1d7" name="CustomerLevels" uri="" description="">
           <version major="1" minor="0" description="" modifiedby="awing" date="2008-07-07T22:39:37.19-04:00"/>
            <vocabularydefinition id="ba912d07-f96d-49ac-a2c4-e619fcec027e" name="Silver" description="Silver Description">


As you can see there you can add as many versions to this file as you want.  However, the ReDeployWiz.exe only publish and import the latest one.

Trying to figure out why this is the behavior, I used my good old friend Reflector. Bringing Reflector on the Rules Engine Deployment Wizard, I see that there is a call to the RuleSetDeploymentDriver namespace. This doImport method calls the driver.ImportAndPublishFileRuleStore to import and publish at the same time.



It seems that there is no way around this call.  It seems to be a limitation on the use of the tool.  This ImportAndPublishFileRuleStore seems to only work on a single version at a time.  If you split the versions into their own file, it can handle it. The down side of this, is that you need to make multiple calls for an import.  And let's face it, the whole nature of versioning the policies and vocabularies becomes very cumbersome when you have over 500+ rules with multiple versions in them [yes, my current project has over 500+ policies and over 30+ vocabularies]

To get around this limitation on the tool, you will have to write your own application to deploy/export all versions of a vocabulary.  To accomplish this you will need to to call the SqlRuleStore namespace instead of the RuleSetDeploymentDriver.  This namespace have the ADD method which contain several overloaded parameters. One of which it allows you to publish or not publish your vocabulary.


Here is my sample code to import ALL versions of a vocabulary in .NET code:

    1 private static int ImportVocabulary(string filename)
    2 {
    3     int result = 0;
    4     // FileRuleStore - gives access to the BRL (XML) file containing policies and vocabularies
    5     FileRuleStore fileRuleStore = null;
    7     // RuleSetDeploymentDriver has the following important methods            
    8     Microsoft.BizTalk.RuleEngineExtensions.RuleSetDeploymentDriver dd = new Microsoft.BizTalk.RuleEngineExtensions.RuleSetDeploymentDriver();
   10     // SqlRuleStore - gives access t0 the rule engine database
   11     SqlRuleStore sqlRuleStore = (SqlRuleStore)dd.GetRuleStore();
   13     //Get VocabularyInfoCollection object based on the file
   14     fileRuleStore = new FileRuleStore(filename);
   15     VocabularyInfoCollection vocabularyInfoList = fileRuleStore.GetVocabularies(RuleStore.Filter.All);
   16     foreach (VocabularyInfo vocabularyInfo in vocabularyInfoList)
   17     {
   18         string vocabularyNameWithVer = string.Format("{0}.{1}.{2}", vocabularyInfo.Name, vocabularyInfo.MajorRevision, vocabularyInfo.MinorRevision);
   19         ExtractVocabularyNameMajorMinor(vocabularyNameWithVer);
   20         VocabularyInfo vi = new VocabularyInfo(App.vocabularyName, App.vocabularyMajorVer, App.vocabularyMinorVer);
   21         Vocabulary oVoc = fileRuleStore.GetVocabulary(vi);
   22         sqlRuleStore.Add(oVoc, App.publishVocabulary);
   23     }
   24     return result;
   25 }

There, now you don't have to be bound to import a single vocabulary version every time you need to move your rules from DEV to UAT to PROD.

Hope this saves someone lots of time and grief.  Happy BRE'ing... ;)

No comments: