En esta publicación, proporcionaremos una introducción básica a nuestro Lenguaje de consulta empresarial fluido , que es una tecnología complementaria a BQL. Pero antes de hacerlo, vamos a repasar un poco nuestro Business Query Language (BQL) para proporcionar algo de contexto a aquellos de vosotros que estéis leyendo este post y seáis nuevos en la plataforma Acumatica.
Para consultar y manipular datos de la base de datos de Acumatica, un desarrollador utilizará BQL, que forma parte de la capa de acceso a datos del marco de Acumatica. Las sentencias BQL representan un conjunto específico de consultas de Acumatica que el marco traduce al SQL adecuado requerido por la base de datos back-end. Esto protege al desarrollador de los matices de lenguaje inherentes a los distintos proveedores de bases de datos (lo que permite a Acumatica ser agnóstico con respecto a las bases de datos) y valida estas consultas en el momento de la compilación.
BQL resuelve dos problemas discretos y bastante importantes a los que se enfrentan a menudo los desarrolladores. Uno, una forma sencilla de crear consultas a partir de un conjunto de primitivas predefinidas, y dos, la declaración de consultas a nivel de atributo en C#. Ambos problemas se resuelven mediante el uso de tipos genéricos.
Las secuencias de elementos del mismo nivel en BQL se implementan de forma muy similar a una estructura de lista enlazada, donde cada elemento siguiente debe pasarse como parámetro genérico del anterior. Esto permite a un desarrollador construir una consulta combinando elementos primitivos sin muchos límites. Sin embargo, a menudo para que esta flexibilidad se manifieste, un desarrollador sacrificará la legibilidad y, por tanto, la mantenibilidad.
GIST:
https://gist.github.com/lekker-solutions/61240fcb5b8d2595cb2e3655329e4827
No es de extrañar que los desarrolladores prefieran reescribir la mayoría de sus consultas BQL desde cero, en lugar de intentar analizar y modificar las más antiguas. Si somos sinceros, ¡no podemos culparles! A diferencia de un ordenador, una persona no puede analizar fácilmente estructuras muy anidadas, especialmente cuando no hay una necesidad específica de una estructura anidada.
Existen otros problemas con BQL, como la sobrecarga "numerada" de los componentes de consulta base, múltiples familias de clases select con estructuras superpuestas, así como el problema de equilibrar los paréntesis angulares de las clases genéricas, que se correlacionan bastante mal con los paréntesis de las consultas SQL nativas.
Todos estos problemas apuntan al hecho de que BQL nos proporciona una forma de producir una variedad infinita de consultas. Para los desarrolladores, sin embargo, es muy difícil leer y mantener consultas BQL complejas, debido sobre todo a la estructura del propio lenguaje BQL.
Para abordar estos problemas, uno de nuestros equipos de ingeniería en Acumatica ha ideado una solución creando Fluent BQL.
Qué es Fluent BQL
A diferencia de BQL, que utiliza declaraciones de clases genéricas similares a funciones, Fluent BQL utiliza declaraciones de clases genéricas fluidas, basadas en el anidamiento de clases genéricas. Esto divide y organiza de forma natural los componentes superiores de una consulta, como las uniones y los agregados, y elimina por completo la ambigüedad de los nombres de los comandos. La estructura de la consulta se asemeja más a la estructura SQL, en la que cada sección no depende de otras y sólo puede aparecer en los lugares que se le asignen. El anidamiento de clases en una definición de comando ayuda a reducir el anidamiento de componentes en una declaración de comando.
Al utilizar FBQL, un desarrollador no tiene que elegir una clase de sobrecarga de comando adecuada. En su lugar, sólo tiene que empezar a escribir un comando e IntelliSense le ofrecerá las continuaciones que sean relevantes para el estado actual de la consulta. Además, cabe señalar que las secciones de una consulta no están separadas por comas, lo cual es positivo, ya que no son iguales en cierto sentido, y su recuento sólo puede variar dentro de límites muy discretos.
Now let’s take a look at some code to get a peek at FBQL. With fluent comparisons, a developer has to use PX.Data.BQL.Bql[Type].Field<TSelf> as a base class for the field as illustrated below. This is already the default all across Acumatica today, however, you might find legacy code written by third parties that still have the IbqlField interface instead.
GIST: https://gist.github.com/lekker-solutions/0379133b6b0432e1717fc5e70a0dc005
Tenga en cuenta que todas las constantes del núcleo de Acumatica y los campos de todos los CAD ya son compatibles con las comparaciones fluidas.
Condiciones de fluidez
The Fluent conditions approach uses dot-separated chaining of Tunary conditions. All IbqlUnary classes, including fluent comparisons, of the Acumatica core, can be used with fluent conditions. To append a condition to another one, just use .And<Tunary> or .Or<Tunary> nested classes of the first condition expression.
GIST: https://gist.github.com/lekker-solutions/731f0b2462c5927b97851f4bd1ea61ce
BQL no tiene corchetes explícitos para las condiciones, pero los corchetes podrían añadirse envolviendo una parte de una condición en una cláusula Where adicional, lo que no es una tarea trivial. Junto con los patrones de encadenamiento, la ausencia de corchetes explícitos conduce a una representación de las condiciones no evidente, contraintuitiva y difícil de mantener.
FBQL brings a brackets class, which represents explicit brackets. Further, what is pretty exciting is that now parentheses are represented by angle brackets of the new fluent .And<> and .Or<> classes. Because of this, there is only one case when you may need to use a brackets class explicitly ‒‒ it is when you start your condition with something enclosed in parentheses. If .And<> or .Or<> contains a single comparison, it does not become wrapped in parentheses.
GIST: https://gist.github.com/lekker-solutions/f931b92916d7c8fecc3870b75d065dd2
FBQL también tiene algunas condiciones más complejas muy útiles que no están disponibles (o que son más fáciles de usar).
GIST: https://gist.github.com/lekker-solutions/36524f61e4dc38635c1e17425be25d8a
Algunas comparaciones entre FBQL y BQL
* Joins are not actually a section of a query, in comparison to other its sections such as Where<>, Aggregate<>, and OrderBy<>, that are containers for some query elements.
** Todas las vistas que contienen agregación son de sólo lectura por defecto.
GIST: https://gist.github.com/lekker-solutions/cde0f434d8e111e3a1b18eeb655d6e01
Claves foráneas en FBQL
Otra función muy útil a la hora de diseñar una consulta con muchas uniones son las nuevas definiciones de claves foráneas presentes en los CAD. Esto acelerará la programación de una consulta grande que consulte muchas tablas. Veamos primero cómo se definen en el DAC:
GIST: https://gist.github.com/lekker-solutions/e37513feb79b7b9b5b5f2db1c449373a
Dentro de la clase FK se define otra clase, InventoryItemFK, que especifica que PAModelGenXRef.inventoryID es una referencia de clave externa a la clave primaria (PK) de la tabla InventoryItem. Echemos un vistazo a cómo se define allí:
GIST: https://gist.github.com/lekker-solutions/73d00938acf89275f6e454f05f796ba3
Podemos utilizar estas definiciones en FBQL.
GIST: https://gist.github.com/lekker-solutions/e17021994eed8e0fbd356bc857fecfbd
Puede que esto no sea muy importante en este caso, en el que la clave foránea/primaria es un único campo, pero en los casos en los que se trata de una clave compuesta por 2 o 3 campos, puede reducir el tamaño de la consulta de forma significativa.
El FBQL se deriva del BQL
Las siguientes tres sencillas directrices que FBQL implementa ayudan a aumentar en gran medida la legibilidad y la facilidad de mantenimiento de las consultas FBQL en comparación con las consultas BQL clásicas.
- Utilizar un patrón de declaración de clases genéricas fluido, en lugar de un patrón de declaración de clases genéricas clásico similar a una función.
- Utilice contenedores (o matrices) de componentes, en lugar de cadenas (o listas enlazadas) de componentes.
- Uso de una familia de Selects y una única búsqueda y vistas basadas en la familia Select, en lugar de tres familias similares.
Yet it is important to keep in mind that FBQL doesn’t replace BQL – FBQL complements it! They can be used together in the same file or class, or even query (you can use FBQL . Where<> in a Bql Where statement, etc, without any naming conflicts. Moreover, FBQL is based on BQL, since the FBQL-command delegates all the querying work to a corresponding BQL-command. All that FBQL tries to achieve is a much higher level of convenience for developers.
Resumen
Hemos dedicado tiempo en este post a presentarle una de nuestras ofertas tecnológicas para desarrolladores, el Fluent Business Query Language - FBQL, y esperamos haber articulado su valor para los desarrolladores que crean aplicaciones e integraciones con la sólida plataforma ERP basada en la nube de Acumatica. FBQL ayudará a los desarrolladores a mantener una biblioteca de consultas haciéndolas mucho más fáciles de leer. Esto se consigue fundamentalmente cambiando la estructura inherente del propio lenguaje BQL. No sustituye a BQL, per se, sino que ofrece un lenguaje de consulta complementario que puede utilizarse conjuntamente, de forma práctica, lo que permite a los desarrolladores aumentar su eficiencia a la hora de escribir y mantener una serie de consultas complejas.
He aquí un resumen de las principales características:
- Uso de un patrón de declaración de clases genéricas fluido, en lugar de un patrón de declaración de clases genéricas clásico de tipo funcional;
- Segregación intuitiva de las secciones de consulta;
- Construcción de condiciones mejorada, simplificada e intuitiva;
- Campos/constantes/funciones fuertemente tipados y comprobación estática de tipos en condiciones;
- Uso de opciones/pistas en lugar de sobrecargas numeradas de componentes de consulta;
- Operaciones binarias infijas;
- El equilibrio natural de los corchetes angulares; y
- Soporte nativo de IntelliSense.
Esperamos que esto haya sido útil - especialmente ahora que este post se ha actualizado desde que lo publicamos originalmente allá por 2018.
¡Feliz codificación!