BQL 解析和验证
任何 Acumatica 应用程序开发人员都花费大量时间编写 BQL 代码。与此同时,并非所有人都知道 BQL 类型如何在幕后工作的基本细节。
BQL 的核心是两个关键方法:Parse()
和 Verify()
,由 IBqlCreator
接口声明。大多数常用的 BQL 类型,如 Where<>
,And<>
,Or<>
等,都来自这个界面。
应该承认,这些方法历史上坚持的名称不是很具描述性。可以说更好的替代名称是 PrepareCommandText
和 Evaluate
。
解析
public void Parse(
PXGraph graph,
List<IBqlParameter> pars,
List<Type> tables,
List<Type> fields,
List<IBqlSortColumn> sortColumns,
StringBuilder text,
BqlCommand.Selection selection)
Parse()
的唯一目的是将 BQL 转换为要发送到 DBMS 的 SQL 命令。因此,此方法接受表示当前正在构造的 SQL 命令的 StringBuilder
参数,BQL 创建者将其附加到其自身的 SQL 文本表示形式。
例如,And<>
谓词的 Parse()
方法会将 AND
附加到命令文本,并递归请求所有嵌套 BQL 创建者的翻译。
特别是,And<ARRegister.docType, Equal<ARDocType.invoice>>
将转化为像 "AND "ARRegister.DocType = 'AR'"
这样的东西。
校验
public void Verify(
PXCache cache,
object item,
List<object> pars,
ref bool? result,
ref object value)
与 Parse()
相比,Verify()
纯粹在应用程序级别运行。
给定记录(例如,ARRegister
对象),它可用于计算其上的表达式,包括计算公式和评估条件。
result
参数用于存储布尔条件评估结果。它主要由谓词 BQL 创建者使用,例如 Where<>
。
value
参数用于存储表达式计算结果。例如,BQL Constant<string>
的 value
是该常量的字符串表示。
大多数情况下,BQL 创建者会影响结果或值,但很少会影响两者。
Verify()
方法的一个值得注意的用法是静态 BqlCommand.Meet()
方法,由 PXCache
用来确定给定项是否满足 BQL 命令:
public bool Meet(PXCache cache, object item, params object[] parameters)
{
List<object> pars = new List<object>(parameters);
bool? result = null;
object value = null;
try {
Verify(cache, item, pars, ref result, ref value);
}
catch (SystemException ex) {
throw new PXException(String.Format("BQL verification failed! {0}", this.ToString()), ex);
}
return result == null || result == true;
}
结论
BQL 创建者的真正力量和美丽在于,它们中的大多数可以在数据库和应用程序级别使用,从而实现 Acumatica 的缓存合并机制,并为代码可重用性提供了很好的机会。
例如,当你从数据库中选择记录时,BQL 命令的 Where<>
子句:
- 将提供
Parse()
在命令准备期间将自身转换为 SQL 文本。 - 将在缓存合并期间提供
Verify()
以确定哪些项目已经驻留在缓存Meet()
Where<>
子句条件中,以便将此类缓存项目包含到结果集中。