事实检索器是一个在策略执行期间用于将长期事实实例插入到策略中的组件。 可以实现 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找到简单且完全限定的程序集名称的定义。
可以使用所需的特定于应用程序的逻辑来设计事实检索器,以连接到所需的数据源,将数据断言为引擎中的长期事实,并指定用于刷新或断言长期事实的新实例的逻辑。 在更新之前,最初在引擎中断言并缓存的值将用于后续执行周期。 事实检索器实现返回类似于令牌的对象,可与 factsHandleIn 对象一起使用,以确定是更新现有事实还是断言新事实。 当策略版本首次调用其事实检索器时, factsHandleIn 对象始终为 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;
}
}
}
数据连接绑定
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根据规则条件查询数据库,查询返回的任何行将作为TypedDataRow数据类型断言到引擎的工作内存中。 重新设置 DataConnection 可确保从内存中移除引擎先前执行的行。
事实上,通过事实检索器断言 DataConnection 没有什么好处,只是它提供了一种外部化数据源的方法。