<FetchXmlBuilder> edita una consulta FetchXML sin que nadie escriba FetchXML. Cubre las partes del lenguaje que la gente realmente utiliza — la tabla, las columnas que devuelve, cómo se ordenan las filas y un árbol de filtros de condiciones y grupos anidados — y une tablas relacionadas, agrega y ejecuta lo que construyó.
El componente real frente a los metadatos de este entorno. Elige una tabla, añade una columna o condición, únete a una tabla relacionada y observa cómo el panel FetchXML sigue el ritmo — luego pulsa Ejecutar para ver qué coincide la consulta.
No es lo mismo que FetchXMLBuilder
Esta página trata sobre el componente.
FetchXMLBuilderes la clase C# que compone el mismo XML en código, para un llamador del lado del servidor que construye una consulta manualmente. Producen lo mismo y ninguno necesita el otro.
Cada tabla, columna y relación se elige de lo que realmente tiene el entorno. Eso es deliberado: un nombre lógico escrito a mano produce FetchXML que analiza perfectamente y luego falla contra Dataverse, que es el peor tipo de error que se puede dar a alguien. El usePowerPortalsProFetchXmlMetadata gancho conecta el constructor a los extremos de metadatos en caché del framework, así que los selectores comparten lo que las cuadrículas en la misma página ya han recuperado.
// Todo el cableado en una página de portal.
import { FetchXmlBuilder, usePowerPortalsProFetchXmlMetadata } from '@powerportalspro/react-fluent';
export function QueryEditor() {
const metadata = usePowerPortalsProFetchXmlMetadata();
const [fetchXml, setFetchXml] = useState('');
return <FetchXmlBuilder value={fetchXml} onChange={setFetchXml} metadata={metadata} />;
}
Blazor no necesita cableado: <FetchXmlBuilder> resuelve el propio servicio de metadatos del portal y lee los mismos puntos finales en caché, por lo que sus selectores también comparten lo que las cuadrículas de la página ya han recuperado.
@* La tabla, las columnas y las relaciones provienen del entorno *@
<FetchXmlBuilder @bind-FetchXml="_fetchXml" />
El creador analiza FetchXML en un modelo de documento y lo vuelve a escribir. Cualquier cosa para la que no tenga editor — un atributo de una versión de plataforma más reciente, un elemento escrito por otra herramienta — se lleva sin tocar en lugar de descartarse al cargar, así que abrir una consulta en el editor y guardarla nunca te cuesta una parte silenciosa.
Qué significa eso para una consulta guardada
El formato no se conserva. La sangría y las citas de atributos se normalizan al salir, por lo que una consulta guardada de nuevo a través del constructor es la misma consulta en lugar del mismo texto.
Hay tres formas de entrar, y las tres pasan por el mismo lector:
value hélice. Suministrala onChange para un componente controlado, o úsala defaultValue y deja que el constructor sea dueño de su estado.Lo que llega se comprueba primero. El XML malformado se reporta con su línea y columna, y también cualquier cosa que haga que el editor muestre algo distinto a lo que se escribió — un operador o tipo de enlace que no conoce, una consulta que no nombra ninguna tabla. Esos se rechazan de plano y la consulta que ya aparece en pantalla se deja intacta. Todo lo demás se reporta y sigue aplicando: un elemento o atributo mal escrito, dos tablas compartiendo un alias, una condición que se lee de un alias que nada declara.
Se añade una unión desde el selector de relaciones, por lo que las from columnas y to provienen de la relación en lugar de la memoria. Lo que puede aportar una unión depende de su tipo:
inner, outer y matchfirstrowusingcrossapply — devolven las columnas de la tabla relacionada, de modo que sus columnas puedan proyectarse, ordenarse y compararse.exists, in, any, not any y all — devuelven la fila como mucho una vez y ninguna de las columnas relacionadas. El editor elimina el alias cuando cambias a uno, por lo que el nombre queda libre para otra unión.Sobre "todos"
FetchXML
allno significa lo que su nombre sugiere — coincide con filas que tienen filas relacionadas de las cuales ninguna satisface el filtro, ynot allestá documentado como equivalente aany. Cada tipo se etiqueta por lo que hace en lugar de por su nombre, y una acción de Invertir condiciones sobre un grupo de filtros expresa la lectura que la gente suele querer.
Un filtro es un grupo de condiciones combinadas con y / o o, y los grupos anidan unos dentro de otros hasta la profundidad que necesite la consulta. Cuatro cosas del árbol que merecen la pena conocer, porque cada una responde a una pregunta que FetchXML hace incómoda de formular:
all no significa "todas las filas relacionadas coinciden" — coincide con filas cuyas filas relacionadas ninguna cumple con el filtro — por lo que expresar la lectura intuitiva significa invertir primero. Se ofrece solo cuando cada condición inferior tiene un verdadero opuesto; la mayoría de los operadores de fecha no tienen ninguno, y invertir parte de un filtro parecería invertida y coincidiría con las filas equivocadas.valueof. Seis operadores lo permiten y la plataforma rechaza el resto por completo, por lo que la lista de operadores se estrecha mientras la fila está en ese modo. Los candidatos provienen de cada tabla unida, ya que una condición llega a una columna relacionada nombrando el alias de la unión.Filas que aún no están terminadas
Se describe una condición que carece del valor que necesita su operador, así como un alias que es requerido y vacío, o compartido con otra columna. Los tres producen FetchXML que analiza perfectamente y luego falla — o devuelve silenciosamente las filas incorrectas — por lo que el editor lo dice en lugar de dejarlo para encontrarlo cuando se ejecuta la consulta. Los operadores que no necesitan valor, como
Contains datayToday, están completos por sí solos y nunca se marcan.
Activa Agregado en la sección de Columnas y cada columna dice lo que aporta — un valor calculado a lo largo de las filas, o por qué están agrupadas. Las funciones ofrecidas se reducen al tipo de columna, los alias se vuelven necesarios y se rellenan por ti, una columna de fecha agrupada gana una parte de fecha, y la ordenación cambia a los alias, porque las filas de una consulta agregada son grupos y valores calculados sin columnas por las que ordenar.
<fetch aggregate="true">
<entity name="account">
<attribute name="revenue" alias="sum_revenue" aggregate="sum" />
<attribute name="address1_city" alias="group_address1_city" groupby="true" />
<order alias="group_address1_city" />
</entity>
</fetch>
allowAggregate={false} retira el switch, para un host que lee filas en lugar de totales — una regla evaluada registro a registro, un filtro guardado, en cualquier lugar donde una sola fila de valores calculados no sería una respuesta. Está ausente en lugar de desactivada, porque ningún cambio en la consulta la traería de vuelta. La única excepción es una consulta que ya agrega: mantiene sus controles independientemente de la posición que se establezca, por lo que una pegada en el panel FetchXML aún puede editarse de nuevo en una consulta ordinaria.
// El conmutador Aggregate no se ofrece en absoluto.
<FetchXmlBuilder
metadata={metadata}
table="contact"
allowAggregate={false}
value={fetchXml}
onChange={setFetchXml}
/>
AllowAggregate="false" hace lo mismo en Blazor, con la misma excepción: una consulta que ya agrega mantiene sus controles, por lo que una que se pega en la pestaña FetchXML aún puede editarse de nuevo en una consulta ordinaria.
@* Retira el interruptor agregado *@
<FetchXmlBuilder Table="contact"
AllowAggregate="false"
@bind-FetchXml="_fetchXml" />
Cada sección puede desactivarse, y las secciones se exportan individualmente para un diseño que las necesite en otro lugar — monta <FetchXmlBuilderProvider> y coloca los FetchXml*Section componentes tú mismo. Omitir una sección elimina su interfaz, nunca el FetchXML subyacente: las columnas de una consulta sobreviven intactas con columns: false.
// Un editor de reglas solo con filtros, fijado a una sola tabla.
<FetchXmlBuilder
metadata={metadata}
table="contact"
sections={{ table: false, columns: false, sorts: false, options: false }}
value={fetchXml}
onChange={setFetchXml}
/>
Blazor toma el mismo conjunto como Sections un registro, y las secciones son componentes en sí mismas — cascada a FetchXmlBuilderState y coloca los FetchXml*Section componentes donde un diseño los necesite. Ocultar uno elimina su editor y nunca la consulta detrás de él.
@* Mostrar solo el editor de filtros *@
<FetchXmlBuilder Table="contact"
Sections="_filterOnly"
@bind-FetchXml="_fetchXml" />
@code {
private readonly FetchXmlBuilderSections _filterOnly = new()
{
Table = false, Columns = false, Sorts = false, Options = false,
};
}
allowedTables reduce el selector de tablas a los nombres lógicos que mencionas — para una superficie que no debería consultar todo el entorno, como un generador de informes sobre el puñado de tablas que expone un portal. Omitilo, se ofrecen todas las tablas. Reduce lo que se puede elegir, no lo que se puede mostrar: una consulta que ya nombra una tabla fuera de la lista la mantiene en lugar de ser reescrita silenciosamente, y una tabla relacionada sigue llamándose por su nombre de visualización siempre que una unión la mencione. Las uniones en sí no están restringidas, porque siguen relaciones — una propiedad de la tabla ya elegida.
// El seleccionador ofrece estos tres y nada más.
<FetchXmlBuilder
metadata={metadata}
allowedTables={['account', 'contact', 'opportunity']}
value={fetchXml}
onChange={setFetchXml}
/>
AllowedTables es el equivalente de Blazor, y reduce lo que se puede elegir en lugar de lo que puede mostrarse exactamente de la misma manera.
@* Ofrece tres mesas y ninguna más *@
<FetchXmlBuilder AllowedTables="_tables"
@bind-FetchXml="_fetchXml" />
@code {
private readonly string[] _tables = ["account", "contact", "opportunity"];
}
Supply renderResults y el constructor hacen crecer un panel de Resultados con un botón Ejecutar, y deciden cuándo pulsarlo: una vez que la consulta nombra una tabla y sus columnas, y ningún campo está marcado en rojo. Mostrar filas requiere un cliente de datos que el constructor deliberadamente no tiene, así que el resultado es tuyo — en un portal eso normalmente significa que el framework es propio <MainGrid> sobre la consulta que devuelve la respuesta. Deja el prop apagado y el panel no está ahí.
<FetchXmlBuilder
metadata={metadata}
value={fetchXml}
onChange={setFetchXml}
// El constructor proporciona el botón; esto dice cómo es un resultado.
renderResults={(runnable) => (
<MainGrid
key={runnable.fetchXml}
tableName={runnable.tableName}
customViewDefinitions={[{
id: BUILDER_VIEW_ID,
displayName: 'Builder query',
tableName: runnable.tableName,
fetchXml: runnable.fetchXml,
columns: runnable.columns.map((columnName) => ({ columnName, width: 200 })),
}]}
viewId={BUILDER_VIEW_ID}
/>
)}
/>
En Blazor aparece el mismo panel una vez que se suministra un RenderResults fragmento, y la consulta ejecutable que devuelve lleva la tabla, el FetchXML y los nombres bajo los que vuelven a aparecer las columnas. Si dejas fuera el fragmento, no hay panel.
@* El constructor posee el botón Correr; las filas son tuyas para dibujar *@
<FetchXmlBuilder @bind-FetchXml="_fetchXml">
<RenderResults Context="runnable">
<MainGrid TableName="@runnable.TableName"
CustomViewDefinitions="@BuilderView(runnable)"
ViewIds="[BuilderViewId]" />
</RenderResults>
</FetchXmlBuilder>
@code {
private static readonly Guid BuilderViewId = Guid.Parse("00000000-0000-0000-0000-00000000f001");
private static List<GridViewDefinition> BuilderView(FetchXmlRunnableQuery runnable) =>
[
new()
{
Id = BuilderViewId,
DisplayName = "Builder query",
TableName = runnable.TableName,
FetchXml = runnable.FetchXml,
Columns = [.. runnable.Columns.Select(x => new ViewColumn { ColumnName = x, Width = 200 })],
},
];
}
Nombre | Tipo | Default | Descripción |
|---|---|---|---|
AllowAggregate | bool | True | Si la consulta puede agregarse. Oculta la oferta cuando puede que no. |
AllowedTables | IReadOnlyList<string>? | Las únicas mesas que ofrece el seleccionador, o nada para todos. | |
FetchXml | string? | La consulta está siendo editada. | |
ReadOnly | bool | False | Muestra la consulta sin ofrecer cambios. |
RenderResults | RenderFragment<FetchXmlRunnableQuery>? | Dibuja las filas que devolvió la consulta, lo que también añade la sección de resultados. | |
Sections | FetchXmlBuilderSections | Qué secciones mostrar. Todo menos los resultados, que necesitan un lugar donde dibujarlos. | |
ShowLogicalNames | bool | True | Si las tablas y columnas llevan nombres lógicos junto a sus nombres de visualización — |
Table | string? | Fija la consulta a una tabla, de modo que el selector de tabla aparece pero está deshabilitado. |
AllowAggregateAllowedTablesFetchXmlReadOnlyRenderResultsSectionsShowLogicalNamesTableNombre | Tipo | Descripción |
|---|---|---|
FetchXmlChanged | EventCallback<string> | Se levanta cada vez que una edición cambia la consulta. |
FetchXmlChanged