Welcome to MSDN Blogs Sign in | Join | Help

Sample: Deploying Business Rules Programmatically

The Rule Engine Deployment Wizard, which ships with BizTalk Server 2006, provides a graphical user interface to perform the following operations:

·     Import a policy from a Business Rule Language (BRL) file into the Rule Engine database, and publish the policy

·     Export a policy from the Rule Engine database to a BRL file

·     Deploy a published policy

·     Undeploy a deployed policy

One of the disadvantages of this wizard is that you can perform only one operation at a time. For example, if you need to export two policies, you need to launch the wizard twice. This wizard is also not scriptable and hence cannot be used to easily automate the operations that it supports. For example, you cannot automate the wizard easily from a setup program to automatically import and deploy one or more policies. The DeployRules sample fills this gap, allowing administrators to import, export, deploy, undeploy, and remove policies in a scriptable manner.

Download the attachment, and review the ReadME.doc first.

Posted by spelluru@microsoft.com | 0 Comments
Attachment(s): DeployRules.zip

Sample: Analyzing Objects of the Same Type in a Business Rule

In many scenarios, you will write a business rule against a type and expect the rule engine to separately analyze and act upon each instance of the type that is asserted into the engine. For example, if you write a rule against a .NET type and assert three .NET objects of that type into the rule engine working memory, the rule engine performs match-conflict resolution-action phases on each .NET object separately. In some scenarios, however, you will want to analyze multiple instances of a given type simultaneously in a rule. This sample demonstrates how to analyze multiple instances of a type in a business rule.

(Download the attachment, and then go through the readme.doc first)

BRE Walkthroughs

Hi all,

I added the following walkthroughs to BizTalk Server documentation recently. Please download the latest documentation from: http://www.microsoft.com/downloads/details.aspx?FamilyId=3294DDAF-9F67-409F-A92D-2F6070DC0D1A&displaylang=en

  1. Walkthrough: Creating a Simple Policy
  2. Walkthrough: Testing the Policy
  3. Walkthrough: Invoking the Policy from an Orchestration
  4. Walkthrough: Creating and Using a Vocabulary in the Policy
  5. Walkthrough: Adding a Rule to the Policy
  6. Walkthrough: Modifying the Policy
  7. Walkthrough: Tracking Policy Execution
  8. Walkthrough: Deploying the Policy
  9. Walkthrough: Executing the Policy Programmatically
  10. Walkthrough: Creating a Fact Creator
  11. Walkthrough: Using Database and .NET facts (You will see this one in the next update, not in this one).

As always, any feedback is welcome and appreciated. After you open the BizTalk Server documentation CHM file, navigate to Microsoft BizTalk Server 2006 Help\Development\Developing BizTalk Server Applications\Creating and Using Business Rules\Business Rules Framework Walkthroughs.

Regards,
Sreedhar

 

BizTalk 2004 SP2 - BRE (Business Rule Engine) Fixes

http://support.microsoft.com/kb/905290/

Fix 245451: BRE caches XML fields incorrectly

 

 http://support.microsoft.com/kb/905571/

Fix: 245450: The Rule Engine is not honoring rule priorities correctly in high load

 

http://support.microsoft.com/kb/920136/

FIX: Some Business Rule Engine values in the Windows registry are reset to the default values in BizTalk Server 2004

 

For all the bugs fixed in BTS 2004 SP2, see

http://support.microsoft.com/kb/924330/

 

Posted by spelluru@microsoft.com | 0 Comments
Filed under:

What is the difference between Microsoft.RuleEngine.RuleSetDeploymentDriver and Microsoft.BizTalk.RuleEngineExtensions.RuleSetDeploymentDriver?

The Microsoft.RuleEngine assembly can be used by any .NET application. The BizTalk Server can be considered as one of the consumers of BRE. The Microsoft.BizTalk.RuleEngineExtensions is the extension for BizTalk to provide some additional functionality. The main difference is that the Microsoft.BizTalk.RuleEngineExtensions.RuleSetDeploymentDriver writes out information to the BizTalk tracking database so that rules can be tracked using HAT. If you use the Microsoft.RuleEngine.RuleSetDeploymentDriver class, deployment go a little bit faster (no need to save the rules to the tracking database, but it is not recommended.

In general, you should use the one configured. In BizTalk 2006, the static method Configuration.GetDeploymentDriver() determines what has been configured and returns an instance of that class. This method looks at the registry entries DeploymentDriverAssembly and DeploymentDriverClass under HKLM\Software\Microsoft\BusinessRules\3.0. The default values for these keys are Microsoft.BizTalk.RuleEngineExtensions and RuleSetDeploymentDriver. In other words, the recommended way is to use the one in Microsoft.BizTalk.RuleEngineExtensions namespace.

Posted by spelluru@microsoft.com | 1 Comments
Filed under:

EQUAL predicate beween Object types and Strings - Breaks in 2006

Here is a question I received on my blog:

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 ?

SINCE I don't have an email address to respond to, I am posting the answer here.

ANSWER: This is a known bug that was not caught in the regression test. The SDE (Software Design Engineer) for BRE is aware of the bug and have the fix for it. However, you need to open an issue with our BizTalk support team and have it escalated to (QFE) Quick Fix Engineering team to get the fix.

Regards,
Sreedhar

Posted by spelluru@microsoft.com | 2 Comments
Filed under:

Ideas for BRE samples

Hi all,

I am planning to create more BRE samples. I would really appreciate if you could let me know what kind of BRE samples you are looking for. If you have any feedback on BRE documentation, send it my way.

Thanks & Regards,

------------------------------------------------------

Sreedhar Pelluru, MCSD .NET, MCTS (BizTalk)               

BizTalk Server User Education Team

Microsoft Corporation

------------------------------------------------------

 

Walkthrough: Testing a Simple Policy

Attached: Testing a Simple Policy.zip file contains

  • Word document for "Testing a Simple Policy" walkthrough
  • SamplePO.xml
  • SamplePO2.xml

 

Walkthrough: Creating a Simple Policy (level 200)

Attached: Creating a Simple Policy.zip file contains

  • Word document for "Creating a Simple Policy" walkthrough
  • PurchaseOrder.xsd schema

BRE: Performance Consideration - Documentation in Development

Performance Considerations

Introduction

This topic discusses how the rule engine performs in various scenarios and with different values for the configuration/tuning parameters.

Fact Types

The rule engine takes less time to access .NET facts compared the time it takes to access the XML and database facts. If you have a choice of using either .NET or XML or database fact in a policy, you should consider using .NET facts for higher performance.

Data Table vs. Data Connection

When the size of the data set is small (< 10 or so), the TypedDataTable binding performs better than the DataConnection binding. Where as, the DataConnection binding performs better than the TypedDataTable binding when the data set is large (greater than or equal to 10 rows approximately). Therefore, you should decide whether to use the DataConnection binding or TypedDataTable binding based on the estimated size of the data set.

Fact Retrievers

You can write a fact retriever—an object that implements standard methods and typically uses them to supply long-term and slowly changing facts to the rule engine before the policy is executed. The engine caches these facts and uses them over multiple execution cycles. Instead of submitting a static or fairly static fact each time the you invoke the rule engine, you should create a fact retriever that submits the fact for the first time, and then updates the fact in memory only when it is needed.

Rule Priority

The priority setting for a rule can range on either side of 0, with larger numbers having higher priority. Actions are executed in order from the highest priority to lowest priority. When the policy implements forward-chaining behavior by using Assert/Update calls, the chaining can be optimized by using the priority setting.  For example, assume that Rule2 has a dependency on a value set by Rule1.  Giving Rule1 a higher priority means that Rule2 will only execute after Rule1 fires and updates the value.  Conversely, if Rule2 were given a higher priority, it could fire once, and then fire again after Rule1 fires and updates the fact that Rule2 is using in a condition.  This may or may not result in the correct results, but clearly would have a performance impact versus only firing once. 

Update Calls

The Update function updates the fact that exists in the working memory of the rule engine and causes all the rules using the updated facts in conditions to be reevaluated. The Update function calls can be expensive especially if large set of rules need to be reevaluated because of updating the facts. There are situations where they can be avoided.  For example, consider the following rules:

Rule1:

IF PurchaseOrder.Amount > 5

THEN StatusObj.Flag = true; Update(StatusObj)

Rule2:

IF PurchaseOrder.Amount <= 5

THEN StatusObj.Flag = false; Update(StatusObj)

 

All remaining rules of the policy use StatusObj.Flag in their conditions. Therefore, when Update is called on the StatusObj object, all the rules will be reevaluated. Whatever the value of the Amount field is, all the rules except Rule1 or Rule2 are evaluated twice, once before the Update call and once after the Update call.

 

Instead, you could set the value of the flag field to false prior to invoking the policy and then use only Rule1 in the policy to set the flag. In this case, Update would be called only if the value of the Amount field is greater than 5, and Update function is not called if amount is less than or equal to 5. Therefore, all the rules except Rule1 or Rule2 are evaluated twice only if the value of the Amount field is greater than 5.

Usage of Logical OR Operators

Using an increasing number of logical OR operators in conditions creates additional permutations that expand the analysis network of the rule engine.  From a performance standpoint, you are better off splitting the conditions into atomic rules that do not contain logical OR operators.

Caching Settings

The rule engine uses two caches. The first one is in the update service and the second one is in each BizTalk process. The first time a policy is used, the BizTalk process requests for the policy information from the update service.  The update service retrieves the policy information from the rule engine database, caches it and returns the information to the BizTalk process. The BizTalk process creates a policy object based on that information and stores the policy object in a cache when the associated rule engine instance completes executing the policy. When the same policy is invoked again, the BizTalk process reuses the policy object from the cache if one is available in the cache. Similarly, if BizTalk process requests for the information about a policy from update service, the update service looks for the policy information in its cache if it is available. The update service also checks if there have been any updates to the policy in the database every 60 seconds (1 minute). If there are any updates, the update service retrieves the information and caches the updated information.

 

There are three tuning parameters for the rule engine related to these caches and they are CacheEntries, CacheTimeout, and PollingInterval. You can specify the values for these parameters either in the registry or in a configuration file. The value of the CacheEntries is the maximum number of entries in the cache. The default value of CacheEntries parameter is 32. You may want to increase the value of the CacheEntries parameter to improve performance in some cases. For example, say, you are using 40 policies repeatedly; you may want to increase the value of CacheEntries parameter to 40 to improve the performance. This would allow the update service to cache details of up to 40 policies in memory. While it would cause the BizTalk service to cache up to 40 policy instances in memory. There may be more than one instance of a policy in the cache of BizTalk service.

 

The value of CacheTimeout is the time (in seconds) for entries to age out of the update service cache. In other words, the CacheTimeout value refers to how long a cache entry for a policy is kept in the cache without it being referred. The default value of CacheTimeout parameter is 3600 seconds (1 Hr). It means that, if the cache entry is not referenced with in an hour, it is deleted. In some cases, you may want to increase the value to a higher value to improve the performance. For example, say, the policy is invoked every 2 hrs. You could improve the performance of the policy execution by increasing the value of the CacheTimeout parameter to a value higher than 2 hrs.

 

The PollingInterval parameter to the rule engine defines the time in seconds for the update service to check the rule engine database for updates. The default value for the PollingInterval parameter is 60 seconds (1 minute). If you know that the policies do not get updated at all or they are updated rarely, you could change this value to a higher value to improve the performance.

Side Effects

The ClassMemberBinding, DatabaseColumnBinding, and XmlDocumentFieldBinding classes have a property named SideEffects. This property determines if the value of the bound field/member/column value is cached or not. The default value of the SideEffects property in the DatabaseColumnBinding and XmlDocumentFieldBinding classes is false. Whereas, the default value of the SideEffects property in the ClassMemberBinding class is true. Therefore, when a field of an XML document or a column of a database table is accessed for the second time or later with in the policy, the value is retrieved from the cache. Where as, when a member of a .NET object is accessed for the second time onwards, the value is retrieved from the .NET object, not from the cache. Setting the siddeffects flag of a .NET ClassMemberBinding to false will improve the performance as the value of the field is retrieved from the cache from second time onwards. You can only do this programmatically. The Business Rule Composer tool does not expose the sideeffects flag.

Instances and Selectivity

The XmlDocumentBinding, ClassBinding and DatabaseBinding classes have two properties, Instances and Selectivity. The value of Instances property is the expected number of instances of the class in working memory. The value of Selectivity property is the percentage of the class instances that will successfully pass the rule conditions. The rule engine uses these values to optimize the condition evaluation so that the lowest possible number of instances are used in condition evaluations first and then the remaining instances. If you have prior knowledge of the number of instances of the object, setting the Instances property to that value would improve the performance. Similarly, if you have prior knowledge of the the percentage of these objects passing the conditions, setting the Selectivity to that value would improve the performance. You can only set value for these parameters programmatically. The Business Rule Composer tool does not expose them.

 

Posted by spelluru@microsoft.com | 1 Comments
Filed under:

How to invoke a policy from another policy? (Policy Chaining)

Policy Chaining
This sample demonstrates how to invoke a policy from another policy by calling the Execute method of the Policy class exposed directly by the Microsoft.RuleEngine assembly.

How to Insert XML Nodes from a Business Rule? - XMLHelper class

Inserting XML Nodes from Business Rules
This sample demonstrates how to insert nodes into an XML document and set their values from a business rule by using the XmlHelper class.   

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