BQL 解析和驗證

任何 Acumatica 應用程式開發人員都花費大量時間編寫 BQL 程式碼。與此同時,並非所有人都知道 BQL 型別如何在幕後工作的基本細節。

BQL 的核心是兩個關鍵方法:Parse()Verify(),由 IBqlCreator 介面宣告。大多數常用的 BQL 型別,如 Where<>And<>Or<> 等,都來自這個介面。

應該承認,這些方法歷史上堅持的名稱不是很具描述性。可以說更好的替代名稱是 PrepareCommandTextEvaluate

解析

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<> 子句條件中,以便將此類快取專案包含到結果集中。