Changes to BRE from BTS 2004 to BTS 2006


Here are some of the changes to BRE in BizTalk 2006.


 


Summary:




  • Support for generic types and generic methods


  • Support for nullable types 2


  • Accessing nested members of a class 4


  • Type Casting support 5


  • Invoking Static Members of a Class 6


  • Overriding registry key setting with application configuration file.


  • GetDeploymentDriver method added to Configuration class


  • Clear method added to the Policy class


  • IFactRemover interface added.


  • SqlTimeOut registry key added.


  • Arithmetic and logical operators support double promotion.

      Attachment: Word document with the following information


Support for generic types and generic methods


The rule engine supports using specialized generic types and specialized generic methods in a rule. It does not support using generic types and generic methods themselves in a rule. For example, in a business rule you can use List<int>, but not List<T> (from the System.Collections.Generic namespace in the .NET class library). Currently, the Business Rule Composer tool does not support creating rules by using specialized generic types and specialized generic methods. You must create the rules programmatically by using the rule engine object model. The following sample code demonstrates how to use the List generic class in a business rule:


 


             // Create the condition list IF 1 == 1


                Equal eq = new Equal(new Constant(1), new Constant(1));


 


                // Create the action list


                ActionCollection ac = new ActionCollection();


 


                //Create class binding and class member bindings


 ClassBinding lstClass = new ClassBinding(typeof(System.Collections.Generic.List<int>));


                ArgumentCollection argc = new ArgumentCollection();


                argc.Add(new Constant(3));


                ClassMemberBinding add = new ClassMemberBinding("Add", lstClass, argc);


 


                // Wrapping the .NET binding as a user function


                UserFunction uf = new UserFunction(add);


                ac.Add(uf);


 


                // Create the rule


                Rule rl = new Rule("AddToList", eq, ac);


 


                // Create the policy


                RuleSet rs = new RuleSet("GenericTest");


                rs.Rules.Add(rl);


 


                // Create the .NET List object


                List<int> lst = new List<int>();


                lst.Add(1);


                lst.Add(2);


 


                // Print the list before executing the policy


                Console.WriteLine("Contents of the lists before executing the policy");


                foreach (int i in lst)


                    Console.WriteLine(i);


 


                PolicyTester pt = new PolicyTester(rs);


                pt.Execute(lst);


 


                


                // Print the list after executing the policy


                Console.WriteLine("Contents of the lists before executing the policy");


                foreach (int i in lst)


                    Console.WriteLine(i);


 


Support for nullable types


The rule engine supports using nullable types in a business rule. You can use nullable types in .NET class bindings, XML bindings, and database bindings. Currently, the Business Rule Composer tool does not support using nullable types in a business rule. You can use the nullable types when creating rules programmatically.


You can create a class member binding to a property or a field whose type is a nullable type. You can also create a class member binding to a method that takes a parameter of nullable type and/or returns a value of nullable type. The following sample code demonstrates how to access a nullable field, and how to access a return value of nullable type from a method in a business rule. If you execute a console application with the following code as it is, you will see that the value of the prop field is set to 5. If you do not initialize the prop field in the class or initialize it to null and run the code, you will see that the value of the prop field is set to 1.


using Microsoft.RuleEngine;


namespace UseNullableAsm


{


    class Program


    {


        public class Class1


        {


            public int? prop = 1;


            private int? prop2 = 4;


            public int? GetProp2()


            {


                return prop2;


            }


        }


 


        static void Main(string[] args)


        {


            //Create the class binding for the Class1 class


            ClassBinding cbCls1 = new ClassBinding(typeof(Class1));


 


            //Create the class member binding to the GetProp2 method of Cls1 class


ClassMemberBinding cmGetProp2 = new ClassMemberBinding("GetProp2", cbCls1);


 


            //Create the class member binding to the to GET the value of prop


            ClassMemberBinding cmGetProp = new ClassMemberBinding("prop", cbCls1);


 


            //Create arguments for the prop1 field, which is prop1 + GetProp2()


            UserFunction ufGetProp = new UserFunction(cmGetProp);


            Add addArg = new Add(ufGetProp, new UserFunction(cmGetProp2));


            ArgumentCollection al1 = new ArgumentCollection();


            al1.Add(addArg);


 


            //Set the value of prop to prop1 + cmGetPro2()


            ClassMemberBinding cmProp = new ClassMemberBinding("prop", cbCls1, al1);


 


            //Create a userfunction based on cmProp and add to the action collection


            UserFunction ufProp = new UserFunction(cmProp);


            ActionCollection ac = new ActionCollection();


            ac.Add(ufProp);


 


            //Create the condition list IF prop == 1


            Equal eq = new Equal(ufGetProp, new Constant(1));


 


            //Create the rule


            // If (prop == 1)


            // Then prop = prop + GetProp2()


            Rule rl = new Rule("NullableTestRule", eq, ac);


 


            //Create the condition list IF prop != 1


            NotEqual neq = new NotEqual(ufGetProp, new Constant(1));


 


            //Set the value of prop to prop to 1


            Constant ct = new Constant(1);


            ArgumentCollection al2 = new ArgumentCollection();


            al2.Add(ct);


 


            //Create class member binding to prop field with argument value 1


ClassMemberBinding cmSetProp = new ClassMemberBinding("prop", cbCls1, al2);


 


            //Create a userfunction based on cmSetProp and add to the action collection


            UserFunction ufSetProp = new UserFunction(cmSetProp);


            ActionCollection ac2 = new ActionCollection();


            ac2.Add(ufSetProp);


 


            //Create the second rule


            // If (prop != 1)


            // Then prop = 1


            Rule rl2 = new Rule("NullableTestRule2", neq, ac2);


 


            //Create the policy and add both the rules to the policy


            RuleSet rs = new RuleSet("NulableTestPolicy");


            rs.Rules.Add(rl);


            rs.Rules.Add(rl2);


 


            //Create the .NET object fact


            Class1 cls1Obj = new Class1();


           


            //Print the value of the field prop before executing the policy


            Console.WriteLine("Value of the prop field is " + cls1Obj.prop);


 


            //Execute the policy


            PolicyTester pt = new PolicyTester(rs);


            pt.Execute(cls1Obj);


 


            //Print the value of the field prop after executing the policy


            Console.WriteLine("Value of the prop field is " + cls1Obj.prop);


        }


    }


}


 


You can also use nullable types in database bindings. The following sample code fragment shows you how to use a nullable type in database bindings.


 


DataColumnBinding dcBinding = new DataColumnBinding(“col”, typeof(int?), dbBinding);


 


Similarly, you can use nullable types in XML bindings. The following sample code fragment shows how to use a nullable type in XML bindings.


XMLDocumentFieldBinding xfb1 = new XMLDocumentFieldBinding(typeof(int?),"ID",xdb);


 


Accessing nested members of a class


The rule engine allows you to use a nested property or method of an object in a rule. For example, suppose you have a class named AClass, which has a property named B of type BClass, which has a field named C. The rule engine allows you to build rules accessing the field C by using the A.B.C syntax. However, it is possible to use this syntax only when building the rules programmatically, not when using the Business Rule Composer tool. The following sample code demonstrates how to use a property of an object, which is a property of another object:


             // Create the condition list IF 1 == 1


            Equal eq = new Equal(new Constant(1), new Constant(1));


 


            // Create the action collection


            ActionCollection ac = new ActionCollection();


 


            // Create class binding and class member binding to cField


            // Set the value of cField to "Changed"


            Constant chg = new Constant("Changed");


            ArgumentCollection argCol = new ArgumentCollection();


            argCol.Add(chg);


            ClassBinding lstClass = new ClassBinding(typeof(AClass));


            ClassMemberBinding bBinding = new ClassMemberBinding("bObj", lstClass);


            ClassMemberBinding CBinding = new ClassMemberBinding("cField", bBinding,argCol);


            UserFunction uf_C = new UserFunction(CBinding);


            ac.Add(uf_C);


           


            // Create the rule


            Rule rl = new Rule("ChangeCField", eq, ac);


 


            // Create the policy


            RuleSet rs = new RuleSet("NestedNodeTest");


            rs.Rules.Add(rl);


 


            //Create the facts


            AClass aObj = new AClass();


            Console.WriteLine("The value of aObj.bObj.cField BEFORE executing the policy");


            Console.WriteLine(aObj.bObj.cField);


 


            //Execute the policy


            PolicyTester tester = new PolicyTester(rs);


            tester.Execute(aObj);


 


            Console.WriteLine("The value of aObj.bObj.cField AFTER executing the policy");


            Console.WriteLine(aObj.bObj.cField);


 


Type Casting support


You can use the Cast method of the ClassMemberBinding class to convert an object of one type to an object of another compatible type. Currently, the Business Rule Composer tool does not support creating rules by using the Cast method. You must create the rules programmatically by using the rule engine object model to take advantage of this feature. The following sample code demonstrates how to use the Cast method to convert an instance of the System.Object class to an instance of the Cls2 class.


using Microsoft.RuleEngine;


 


namespace RuleTypeCasting


{


    class Cls1


    {


        //Note that return type is 'object', not Cls2


        public object GetCls2Obj()


        {


            return new Cls2();


        }


    }


 


    class Cls2


    {


        public void Log()


        {


            Console.WriteLine("In Cls2.Log method");


        }


    }


 


    class Program


    {


        static void Main(string[] args)


        {


            //Create the condition list IF 1 == 1


            Equal eq = new Equal(new Constant(1), new Constant(1));


 


            //Create the action collection


            ActionCollection ac = new ActionCollection();


 


            //Create the class binding for the Cls1 class


            ClassBinding cbCls1 = new ClassBinding(typeof(Cls1));


 


            //Create the class member binding for the GetCls2Obj method in the Cls1 class


            ClassMemberBinding cmGetCls2Obj = new ClassMemberBinding("GetCls2Obj", cbCls1);


                       


            //Type casting the return value of GetCls2Obj method (object) to Cls2 type


            cmGetCls2Obj.Cast(typeof(Cls2));


 


            //Create the class member binding to the Log method of Cls2 type


            ClassMemberBinding cmLog = new ClassMemberBinding("Log", cmGetCls2Obj);


 


            //Create a user function based on cmLog and add it to the action collection


            UserFunction ufLog = new UserFunction(cmLog);


            ac.Add(ufLog);


 


            // Create the rule


            Rule rl = new Rule("InvokeLogRule", eq, ac);


 


            // Create the rule set or policy


            RuleSet rs = new RuleSet("InvokeLogPolicy");


            rs.Rules.Add(rl);


           


            //Create the facts


            Cls1 Cls1Obj = new Cls1();


 


            //Execute the policy


            PolicyTester tester = new PolicyTester(rs);


            tester.Execute(Cls1Obj);


           


        }


    }


}


 


Invoking Static Members of a Class


By default, the rule engine requires you to assert an instance of a .NET class to execute a policy that invokes a static member of the .NET class. You can modify this behavior by changing the value of the StaticSupport registry key under HKEY_LOCAL_MACHINE\Software\Microsoft\BusinessRules\3.0 to one of the values in the following table.
















StaticSupport registry value


Rule engine behavior


0


Default value. The rule engine follows the BizTalk Server 2004 model, where the static method is called only when an instance of the .NET class is asserted.


1


An object instance is not required. The static method is called when the rule is evaluated or executed.


2


An object instance is not required. The static method is called at the policy translation time if all parameters are constant. This is a performance optimization because the static method is called only once even though it is used in multiple rules in conditions. Note that static methods used as actions will not be executed at the translation time, but static methods used as parameters may be executed.


 


If you do not see the StaticSupport registry key under HKEY_LOCAL_MACHINE\Software\Microsoft\BusinessRules\3.0, you should add it by performing the following steps.


To add the StaticSupport registry key


1.            Click Start; click Run, type RegEdit, and then click OK.


2.            Expand HKEY_LOCAL_MACHINE, expand Software, expand Microsoft, expand BusinessRules, and then select 3.0.


3.            In the right pane, right-click, point to New, and then click DWORD value.


4.            For Name, type StaticSupport.


If the StaticSupport registry key already exists, and you need to change its value, perform the following steps.


To change the value of the StaticSupport registry key


1.            Click Start, click Run, type RegEdit, and then click OK.


2.            Expand HKEY_LOCAL_MACHINE, expand Software, expand Microsoft, expand BusinessRules, and then expand 3.0.


3.            Double-click the StaticSupport registry key, or right-click it and then click Modify.


 


Overriding registry key setting with application configuration file
The registry entries described in the topic “Rule Engine Configuration and Tuning Parameters” on MSDN ( http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sdk/htm/ebiz_prog_rules_yhjc.asp ) can be overriden by using an application configuration file.


The registry settings are global for all applications that host a rule engine instance. You can override these registry settings at an application level by using the application configuration file. For BizTalk Server applications, the host application is the BTSNTSvc.exe and the configuration file is the BTSNTSvc.exe.config, which you can find in the BizTalk Server installation directory. You need to specify the values for the configuration parameters that you want to override in the application configuration file as show below:


<configuration>


    <configSections>


        <section name="Microsoft.RuleEngine" type="System.Configuration.SingleTagSectionHandler" />


    </configSections>


    <Microsoft.RuleEngine


        UpdateServiceHost="localhost"


        UpdateServicePort="3132"


        UpdateServiceName="RemoteUpdateService"


        CacheEntries="32"


        CacheTimeout="3600"


        PollingInterval="60"


        TranslationTimeout="3600"


        CachePruneInterval="60"


        DatabaseServer="(localhost)"


        DatabaseName="BizTalkRuleEngineDb"


        SqlTimeout="-1"


        StaticSupport="1"


    />


</configuration>


 


GetDeploymentDriver method added to Configuration class


You can deploy policies programmatically by using the RuleSetDeploymentDriver class in the Microsoft.RuleEngine.RuleEngineExtensions namespace. The following sample code demonstrates how to use the RuleSetDeploymentDriver class to deploy a policy named LoanProcessing:


 


string policyName = “LoanProcessing”;


int majorRev = Convert.ToInt16(args[1]);


int minorRev = Convert.ToInt16(args[2]);


RuleSetInfo rsi = new RuleSetInfo(policyName,majorRev,minorRev);


Microsoft.BizTalk.RuleEngineExtensions.RuleSetDeploymentDriver dd;


dd = new Microsoft.BizTalk.RuleEngineExtensions.RuleSetDeploymentDriver();


dd.Deploy(rs);


 


The overloaded constructors of the RuleSetDeploymentDriver class take the names of the rule store database as a parameter. This allows you to deploy policies to a database that your BizTalk Server environment is not configured to use.


 


If you are deploying policies to the database that your BizTalk Server environment is configured to use, you do not have to create the RuleSetDeploymentDriver object in the code. Instead, you can request the rule engine to create a RuleSetDeploymentDriver object for you by invoking the GetDeploymentDriver method of the Configuration class in the System.RuleEngine namespace. The following sample code demonstrates how to invoke the GetDeploymentDriver method:


 


Microsoft.BizTalk.RuleEngineExtensions.RuleSetDeploymentDriver dd;


dd = new Microsoft.RuleEngine.Configuration.GetDeploymentDriver();


The GetDeploymentDriver method retrieves the values of the DeploymentDriverAssembly and DeploymentDriverClass registry keys under HKEY_LOCAL_MACHINE\Software\Microsoft\BusinessRules\3.0, and creates an instance of DeploymentDriverClass. The following table shows the default values of these two registry keys.













Registry key


Value


DeploymentDriverAssembly


Microsoft.BizTalk.RuleEngineExtensions


DeploymentDriverClass


Microsoft.BizTalk.RuleEngineExtensions.RuleSetDeploymentDriver


The RuleSetDeploymentDriver class implements the IRuleSetDeploymentDriver interface. You can develop your own policy deployment driver by creating a class that implements the IRuleSetDeploymentDriver interface and change the values for the registry keys described above as appropriate.


Clear method added to the Policy class


Clear method is added to the Policy class. Here are the important methods of the Policy class and their descriptions.
















Method


Description


Execute


Adds the specified short-term facts into the rule engine's working memory and executes the policy using Match-Conflict Resolution-Action algorithm. For more information on Match-Conflict Resolution-Action algorithm, see Condition Evaluation and Action Execution .


Dispose


Releases the resources used by the rule engine for executing the policy.


Clear


Clears or resets the working memory and the agenda of the rule engine instance created for executing the policy.


 


IFactRemover interface added


You can optionally implement the IFactRemover interface on a fact retriever component. The rule engine invokes the UpdateFactsAfterExecution method of the IFactRemover interface when the policy is disposed. This provides an opportunity to you to do any post-execution work such as committing any database changes or retracting any object instances from the rule engine's working memory.


 


SqlTimeOut registry key added


SqlTimeOut Registry key is added under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\BusinessRules\3.0.












Name


Description


Default Value


SqlTimeout


Timeout value for SQL commands that access the SQL rule store. The value for this key is interpreted as follows:


< 0 - Uses the .NET default value (30 seconds)


= 0 - Unlimited timeout


> 0 - Maximum time for a query before it times out


-1


 


Arithmetic and logical operators support double promotion


Arithmetic operators such as addition, subtraction, multiplication, and division automatically promote a smaller operand type to a larger operand type if the types are different. The rule engine also supports double promotion if both the operands can be promoted to a common type.


 


For logical operators, when operands are of different types, the rule engine converts type of one of the parameters to match the type of the other parameter or converts types of both the parameters to a common type before evaluating the expression.


 

Changes to BRE in BizTalk 2006.xml

Comments (7)

  1. sandeep02 says:

    Great!!!
    Thanks for the Blog!!!

    It would be really  great if there was a easier way to get the ClassBindings of a policy at the time of executions to add the facts required for execution.

    The present way is by calling the RuleSetDeploymentDriver, getting the RuleSet and calling the RuleSetBindingFinder for that particular ruleset from the SQL Rule Store.

    Any new way to get the classbindings easily?

    Thanks,
    Sandeep Kesiraju

  2. Hi Sandeep,

    No. There is no new/easier way to get class bindings in BTS 2006. You still need to use RuleSetBindingFinder on a RuleSet object to obtain class bindings. How you get/create the RuleSet object is up to you. You can create it using API or from a rule store.

    Hope this helps,

    Sreedhar

  3. Spaceman.Spiff says:

    We have hundreds of BTS2004 rules where we use the EQUAL predicate beween Object types and Strings.

    Now I discovered that BTS2006 does not permit this anymore. Why is it undocumented? How do I migrate those Rules in BTS2006 ?

       Regards

         Tom

Skip to main content