如何创建事实检索器

事实检索器是在策略执行期间用来将长期事实实例添加到该策略中的组件。 你可以实现 IFactRetriever 接口,并配置策略版本以运行时使用此实现来引入长期事实实例。 如果为事实检索器配置了该特定版本,则策略版本将调用每个执行周期的事实检索器实现 UpdateFacts 方法。

可以选择在事实检索器组件上实现 IFactRemover 接口。 释放策略时,规则引擎将调用 IFactRemover 接口的 UpdateFactsAfterExecution 方法。 这使您可以有机会进行执行后工作,例如提交任何数据库更改或从规则引擎的工作内存取消任何对象实例。

为策略指定事实检索器

您可以使用以下代码配置规则集,使用“MyAssembly”程序集中的“Retriever”类作为事实检索器。

RuleEngineComponentConfiguration fr = new RuleEngineComponentConfiguration("MyAssembly", "Retriever");
RuleSet rs = new RuleSet("ruleset");
// associate the execution configuration with a ruleset
RuleSetExecutionConfiguration rsCfg = rs.ExecutionConfiguration;
rsCfg.FactRetriever = factRetriever;

注意

如果指定简单程序集名称(如 MyAssembly)作为 RuleEngineComponentConfiguration 构造函数的第一个参数,则 BizTalk 规则引擎将假定它是私有程序集,并在应用程序文件夹中查找该程序集。 如果指定完全限定的程序集名称,例如 MyAssembly、Version=1.0.0.0、Culture=neutral、PublicKeyToken=a310908b42c024fe,则规则引擎假定它是共享程序集,并查找全局程序集缓存 (GAC) 中的程序集。 可以在 上找到简单且完全限定的程序集名称的定义 https://go.microsoft.com/fwlink/?LinkId=64535

您可以使用所需的特定于应用程序的逻辑来设计事实检索器以连接所需的数据源,将该数据作为长期事实添加到到引擎中,并指定刷新或向引擎中添加新的长期事实实例的逻辑。 只有在更新之后,最初添加到引擎中并随后缓存的值才将用于后续的执行循环。 事实检索器实现返回类似于令牌的对象,并可以与 factHandleIn 对象一起用于确定是更新现有事实还是断言新事实。 当策略版本首次调用其事实检索器时, factHandleIn 对象始终为 null,然后在事实检索器执行后采用返回对象的值。

请注意,对于同一规则引擎实例,一个长期事实只需添加一次。 例如,在业务流程中使用"调用 规则 "形状时,策略实例将移动到内部缓存中。 此时,将取消所有短期事实,并保留所有长期事实。 如果同一策略由同一业务流程实例或同一主机中的不同业务流程实例再次调用,则将从缓存中提取此策略实例并重新使用。 在某些批处理环境中,可以创建同一策略的多个策略实例。 如果创建新的策略实例,则必须确保添加了正确的长期事实。

此外,您需要编写自定义代码以实现以下策略:

  • 了解何时更新长期事实

  • 跟踪规则引擎所使用的长期事实

    下面的示例代码显示了不同的事实检索器实现,它们使用不同的绑定类型与 MyPolicy 相关联以将 MyTableInstance 添加为长期事实。

DataTable 绑定

using System;
using System.Xml;
using System.Collections;
using Microsoft.RuleEngine;
using System.IO;
using System.Data;
using System.Data.SqlClient;
namespace MyBizTalkApplication.FactRetriever
{
   public class myFactRetriever:IFactRetriever
   {
      public object UpdateFacts(RuleSetInfo rulesetInfo, Microsoft.RuleEngine.RuleEngine engine, object factsHandleIn)
      {
         object factsHandleOut;
         if (factsHandleIn == null)

         {
            SqlDataAdapter dAdapt = new SqlDataAdapter();
            dAdapt.TableMappings.Add("Table", "CustInfo");
            SqlConnection conn = new SqlConnection("Initial Catalog=Northwind;Data Source=(local);Integrated Security=SSPI;");
            conn.Open();
            SqlCommand myCommand = new SqlCommand("SELECT * FROM CustInfo", conn);
            myCommand.CommandType = CommandType.Text;
            dAdapt.SelectCommand = myCommand;
            DataSet ds = new DataSet("Northwind");
            dAdapt.Fill(ds);
            TypedDataTable tdt = new TypedDataTable(ds.Tables["CustInfo"]);
            engine.Assert(tdt);
            factsHandleOut = tdt;
         }

         else
            factsHandleOut = factsHandleIn;
         return factsHandleOut;
      }
   }
}

DataRow 绑定

using System;
using System.Xml;
using System.Collections;
using Microsoft.RuleEngine;
using System.IO;
using System.Data;
using System.Data.SqlClient;
namespace MyBizTalkApplication.FactRetriever
{
   public class myFactRetriever:IFactRetriever
   {

      public object UpdateFacts(RuleSetInfo rulesetInfo, Microsoft.RuleEngine.RuleEngine engine, object factsHandleIn)
      {
         object factsHandleOut;
         if (factsHandleIn == null)

         {
            SqlDataAdapter dAdapt = new SqlDataAdapter();
            dAdapt.TableMappings.Add("Table", "CustInfo");
            SqlConnection conn = new SqlConnection("Initial Catalog=Northwind;Data Source=(local);Integrated Security=SSPI;");
            conn.Open();
            SqlCommand myCommand = new SqlCommand("SELECT * FROM CustInfo", conn);
            myCommand.CommandType = CommandType.Text;
            dAdapt.SelectCommand = myCommand;
            DataSet ds = new DataSet("Northwind");
            dAdapt.Fill(ds);
            TypedDataTable tdt = new TypedDataTable(ds.Tables["CustInfo"]);

            // binding to the first row of CustInfo table
            TypedDataRow tdr = new TypedDataRow(ds.Tables["CustInfo"].Rows[0],tdt);
            engine.Assert(tdr);
            factsHandleOut = tdr;
         }
         else
            factsHandleOut = factsHandleIn;
         return factsHandleOut;
      }
   }
}

下面的示例代码演示了如何在事实检索器实现中添加 .NET 和 XML 事实。

using System;
using System.Xml;
using System.Collections;
using Microsoft.RuleEngine;
using System.IO;
using System.Data;
using System.Data.SqlClient;
namespace MyBizTalkApplication.FactRetriever
{
   public class myFactRetriever:IFactRetriever
   {
      public object UpdateFacts(RuleSetInfo rulesetInfo, Microsoft.RuleEngine.RuleEngine engine, object factsHandleIn)
      {
         object factsHandleOut;
         if (factsHandleIn == null)
         {
            //create .NET object instances
            bookInstance = new Book();
            magazineInstance = new Magazine();

            //create an instance of the XML object
            XmlDocument xd = new XmlDocument();

            //load the document
            xd.Load(@"..\myXMLInstance.xml");

            //create and instantiate an instance of TXD
            TypedXmlDocument doc = new TypedXmlDocument("mySchema",xd1);

            engine.Assert(bookInstance);
            engine.Assert(magazineInstance);
            engine.Assert(doc);
            factsHandleOut = doc;
         }
         else
            factsHandleOut = factsHandleIn;
         return factsHandleOut;
      }
   }
}

DataConnection 绑定

using System;
using System.Xml;
using System.Collections;
using Microsoft.RuleEngine;
using System.IO;
using System.Data;
using System.Data.SqlClient;
namespace MyBizTalkApplication.FactRetriever
{
   public class myFactRetriever:IFactRetriever
   {
      public object UpdateFacts(RuleSetInfo rulesetInfo, Microsoft.RuleEngine.RuleEngine engine, object factsHandleIn)
      {
         object factsHandleOut;

         {
            string strCmd = "Initial Catalog=Northwind;Data Source=(local);Integrated Security=SSPI;";
            SqlConnection conn = new SqlConnection(strCmd);
            DataConnection dc = new DataConnection("Northwind", "CustInfo", conn);

            engine.Assert(dc);
            factsHandleOut = dc;
         }
         return factsHandleOut;
      }
   }
}

请注意,从事实检索器提供 DataConnections 时,应始终重新组合,如前面的代码示例所示。 引擎实例使用 DataConnection 根据规则条件查询数据库,查询返回的任何行都会作为 TypedDataRows 断言到引擎的工作内存中。 重新组合 DataConnection 可确保从内存中清除先前执行引擎的行。

事实上,通过事实检索器断言 DataConnection 没有优势,只不过它提供了一种将数据源外部化的方法。