Blog

View Blog

Okt 16

Written by: Rainer Worbis
16.10.2005

The target (for this example) is to create an custom component that changes a date value to the next weekday (based on a stored function in a database). This component is used in a rule which should unter certain circumstances assign only weekdays to a date.

To achieve this on has first to imlement the actual class which mapps a date to the next weekday. In my case the next weekday is calculated in an stored function defined in our application database.

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Diagnostics;
namespace Cubido.BizTalk.Tools
{
 public class DateTool
 {
  public DateTool()
  {
   if(!EventLog.SourceExists("Cubido.BizTalk.Tools"))
    EventLog.CreateEventSource("Cubido.BizTalk.Tools", "Cubido.BizTalk.Tools");
  }
  public string NextWeekDayString(DateTime date, string calendarId, string connectString)
  {
   try
   {
    SqlConnection con = new SqlConnection(connectString);
    con.Open();
    SqlCommand cmd = con.CreateCommand();
    cmd.CommandText = "SET DATEFIRST 1; SELECT dbo.JuxtaposedWorkdayAfter(@CalendarID, @Date)";
    cmd.Parameters.Add("@CalendarID", SqlDbType.VarChar, 12).Value = calendarId;
    cmd.Parameters.Add("@Date", SqlDbType.DateTime).Value = date;
    date = (DateTime) cmd.ExecuteScalar();
    con.Close();
   }
   catch(Exception e)
   {
    EventLog eventLog = new EventLog();
    eventLog.Source = "Cubido.BizTalk.Tools";
    eventLog.WriteEntry(e.ToString(), EventLogEntryType.Error);
   }
   string curdate = date.ToString("yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture);
   string curtime = date.ToString("T",System.Globalization.CultureInfo.InvariantCulture);
   return curdate + "T" + curtime + ".000";
  }
 }
}

A few thing are notable about this piece of code:

  • the function NextWeekDayString returns a String and not a DateTime. Returning a DateTime resulted in some errors which I could not follow and with String as return value it works like a charm. The string representation of the date value is such that the date is recognized by the Microsoft SqlServer as valid date.
  • The Parameter calendarId and connectString are just my way to specify the neccessary type of calendar used (the application allowes different calendars in different situations) and the connect string to our applications database. Both values are defined in the vocabulary as constants.

The second piece of code is not so ovious - but it is needed nevertheless. It's just a class needed by the rule composer for manageing the fact.

using System;

using Microsoft.RuleEngine;

namespace Cubido.BizTalk.Tools
{
 ///


 /// Summary description for FactCreator.
 ///

 public class FactCreator : IFactCreator
 {
  public object[] CreateFacts(RuleSetInfo rsi)
  {
   object[] o = new object[1];
   o[0] = new Cubido.BizTalk.Tools.DateTool();
   return o;
  }
  public Type[] GetFactTypes(RuleSetInfo rsi)
  {
   Type[] t = new Type[1];
   t[0] = new Cubido.BizTalk.Tools.DateTool().GetType();
   return t;
  }
 }
}

The interface FactCreator (implemented in an Assembly found in '...\Program Files\Microsoft BizTalk Server 2004\Microsoft.RuleEngine.dll') has to be imlemented and the content of the object array retured matches all the functions that should be accessed from the Business Rule Composer.

The assembly (or assemblies if you have more of them) have to reside in the global assembly cache. For me it was usefull to set the version of the assembly to '1.0.0.0' (in the AssemblyInfo.cs) and define a post build step which removes the old assembly and adds the new on from/to the GAC.

Having come so far the C# programming is over, the component can be used within the Business Rule Composer. To do so one must add the component in the Fact Explorer. After that it can be used within any rule either in the Condition part or in the Then part.

If you do some testing within the Business Rule Composer you have to add the Assembly with the class implementing the IFactCreator interface to the fact creators in the Test Policy dialog.

When the Rule is accessed from an orchestration, the class which implements the custom function has to be assigned to a variable (Variables -> New Variable) and provided as parameter in the Call Rule shape. 

Tags:

11 comments so far...

Sorry - privat

Rainer, kannst Du mich bitte anmailen?

Thomas Wiesinger (HTL 1986)
tomhtl@wiesinger.org

By Anonymous on   07.03.2008

Re: Custom C# Functions for the BizTalk 2004 Business Rule Composer

Can we add two strings inside the Biz Talk Rule Composer

By Anonymous on   07.03.2008

Re: Custom C# Functions for the BizTalk 2004 Business Rule Composer

yes you can.....by having 2 variables of type string

By Anonymous on   07.03.2008

Re: Custom C# Functions for the BizTalk 2004 Business Rule Composer

Do we have to "call" FactCreator in some way in the rule?

By PA on   09.04.2008

Re: Custom C# Functions for the BizTalk 2004 Business Rule Composer

Do we have to "call" FactCreator in some way in the rule?

By PA on   09.04.2008

Re: Custom C# Functions for the BizTalk 2004 Business Rule Composer

Do we have to "call" FactCreator in some way in the rule?

By PA on   09.04.2008

Re: Custom C# Functions for the BizTalk 2004 Business Rule Composer

Do we have to "call" FactCreator in some way in the rule?

By PA on   09.04.2008

Re: Custom C# Functions for the BizTalk 2004 Business Rule Composer

You rock! - This explanation and sample provided me with exactly what I needed and couldn't find from Microsoft. Since I wasn't submitting a fact, I never thought I might need IFactCreator - but you are right: I do.

Thank you very much.

(and for PA: no, you dont - it just needs to be there)

By Steve on   16.04.2008

Re: Custom C# Functions for the BizTalk 2004 Business Rule Composer

Sorry for multiple posting by the way.

I have now developed my own custom class, and made a rule using the method from it. When test the rule, it seems fine. But when actually running it from the application, the rule will not fire when I use this method from the custom .net component! So here is some code: (hope for some help...)

public class TimeDifference : Microsoft.RuleEngine.IFactCreator
{
public TimeDifference()
{

}
public int StringToInt(string value)
{
return Int32.Parse(value);
}

#region IFactCreator Members

public object[] CreateFacts(RuleSetInfo ruleSetInfo)
{
return new object[] { new TimeDifference() };
}
public Type[] GetFactTypes(RuleSetInfo ruleSetInfo)
{
Type converterType = this.GetType();
return new Type[] {converterType };
}

#endregion
}

Here is my simple rule:

//in the if panel
TimeDifference.StringToInt(3) is less than or equal to 10

Using this will make the rule not fire. Removing this and use other method from not custom .net component will work.

By the way, I am testing on Biztalk 2006 R2

By PA on   16.04.2008

Re: Custom C# Functions for the BizTalk 2004 Business Rule Composer

GLT10a02peng24
nice article, i got good information, thanks for posting..chanel handbags

By chanel handbags on   24.02.2010

Re: Custom C# Functions for the BizTalk 2004 Business Rule Composer

I am very pleased to find your site on the web as it represents a great value for me and my family. autism resources

By London on   09.03.2010

Your name:
Title:
Comment:
Add Comment    Cancel  

Newsletter

Sie möchten im Newsletter über aktuelle technische Entwicklungen und Neuigkeiten rund um cubido informiert werden?

Newsletter abonnieren ...

Blog