Oharra
Baimena behar duzu orria atzitzeko. Direktorioetan saioa has dezakezu edo haiek alda ditzakezu.
Baimena behar duzu orria atzitzeko. Direktorioak alda ditzakezu.
Importante
Le desaconsejamos encarecidamente devolver todas las columnas de una tabla con su consulta. Devolver todas las columnas hará que sus aplicaciones se ejecuten más lentamente y puede provocar errores de tiempo de espera. Debe especificar el número mínimo de columnas que se van a recuperar junto con sus datos. Si establece la propiedad ColumnSet.AllColumns en true, se devuelven los datos de todas las columnas. Si no establece ninguna columna, solo se devuelve el valor de clave principal del registro. Esto es opuesto al comportamiento mediante FetchXml, donde se devuelven todas las columnas si no se especifica ninguna.
Use la clase ColumnSet para especificar los nombres de las columnas que se devolverán con la consulta. Use el valor AttributeMetadata.LogicalName para cada columna. Los nombres lógicos siempre están en minúsculas.
Puede especificar las columnas con el constructor ColumnSet(String[]) al inicializar QueryExpression:
QueryExpression query = new("account")
{
ColumnSet = new ColumnSet("name", "accountclassificationcode", "createdby", "createdon")
};
Y puede usar los métodos ColumnSet.AddColumn o ColumnSet.AddColumns para agregar columnas adicionales a la propiedad QueryExpression.ColumnSet después de que QueryExpression se haya inicializado.
QueryExpression query = new("account");
query.ColumnSet.AddColumn("name");
query.ColumnSet.AddColumns("accountclassificationcode", "createdby", "createdon");
Nota:
Algunas columnas no son válidas para lectura. La propiedad AttributeMetadata.IsValidForRead indica si una columna es válida para lectura. Si incluye los nombres de estas columnas, no se devuelve ningún valor.
La propiedad ColumnSet.Columns es Microsoft.Xrm.Sdk.DataCollection<cadena> que extiende System.Collections.ObjectModel.Collection<T>clase, por lo que también puede usar los métodos de esas clases de base para interactuar con las cadenas de la colección.
Selección de columnas para tablas combinadas
Al combinar tablas mediante QueryExpression, se usa la clase LinkEntity. La propiedad LinkEntity.Columns es un ColumnSet, por lo que definirá las columnas que se devolverán para las tablas unidas del mismo modo.
Clases de campo enlazadas anticipadamente
Si está utilizando clases de campo de enlace temprano generadas usando el comando pac modelbuilder con el interruptor emitfieldsclasses habilitado, puede usar las constantes generadas para todos los nombres de campos en lugar de usar los nombres lógicos directamente como cadenas.
QueryExpression query = new(Account.EntityLogicalName)
{
ColumnSet = new ColumnSet(
Account.Fields.Name,
Account.Fields.AccountClassificationCode,
Account.Fields.CreatedBy,
Account.Fields.CreatedOn)
};
Esto ayuda a evitar errores en tiempo de ejecución debido a la escritura del nombre incorrecto. Más información sobre:
- Generar clases con enlace de tipo de compilación para el SDK para .NET
- Programación en tiempo de ejecución y en tiempo de compilación con SDK para .NET
Alias de columna
Los alias de columna se suelen usar para las operaciones de agregado, pero también funcionan para recuperar filas, por lo que podemos introducirlos aquí.
Agregue instancias XrmAttributeExpression a la colección ColumnSet.AttributeExpressions para especificar un nombre de columna único para los resultados devueltos. Para cada instancia, establezca estas propiedades:
| Propiedad | Description |
|---|---|
| AttributeName | Nombre lógico de la columna |
| Alias | Nombre único para que la columna aparezca en los resultados |
| AggregateType | Cuando no agregue datos, utilice el miembro XrmAggregateType.None. Este es el valor predeterminado, por lo que no es necesario establecerlo si no usa la agregación.
Más información sobre cómo agregar datos con QueryExpression |
Cada columna devuelta debe tener un nombre único. De forma predeterminada, los nombres de columna devueltos para la tabla de la consulta son los valores de columna LogicalName . Todos los nombres lógicos de columna son únicos para cada tabla, por lo que no puede haber nombres duplicados dentro de ese conjunto.
Cuando se usa linkEntity para combinar tablas, puede establecer la propiedad EntityAlias para la LinkEntity que representa la tabla combinada. Los nombres de columna de la propiedad LinkEntity.Columns siguen esta convención de nomenclatura: {Linked table LogicalName or alias}.{Column LogicalName}. Esto impide cualquier nombre de columna duplicado.
Sin embargo, cuando especifica un alias de columna usando la propiedad XrmAttributeExpression.Alias, el LinkEntity.EntityAlias o el valor del nombre lógico de la tabla no se antepone al valor del alias. Debe asegurarse de que el valor del alias sea único. Si el valor no es único, puede esperar este error:
Nombre:
QueryBuilderDuplicateAlias
Código:0x80041130
Número:-2147217104
Mensaje:< alias value > is not a unique alias. It clashes with an autogenerated alias or user provided alias
Ejemplo de alias de columna
En este método de ejemplo se SimpleAliasOutput usan alias y nombres lógicos de las columnas. Debido a esto, los resultados que usan alias se devuelven como AliasedValue. Para tener acceso al valor de tipos como OptionSetValue o EntityReference, debe convertir el valor.
En este ejemplo, los alias solo se especifican para las accountclassificationcodecolumnas , createdbyy createdon . La name columna no usa un alias. Este método depende del paquete NuGet ConsoleTables para representar la tabla.
/// <summary>
/// Output the entity attribute values with aliases
/// </summary>
/// <param name="service">The authenticated IOrganizationService instance</param>
static void SimpleAliasOutput(IOrganizationService service)
{
QueryExpression query = new("account")
{
TopCount = 3,
ColumnSet = new ColumnSet("name")
{
AttributeExpressions = {
new XrmAttributeExpression{
AttributeName = "accountclassificationcode",
Alias = "classificationcode"
},
new XrmAttributeExpression{
AttributeName = "createdby",
Alias = "whocreated"
},
new XrmAttributeExpression{
AttributeName = "createdon",
Alias = "whencreated"
}
}
}
};
//Retrieve the data
EntityCollection entityCollection = service.RetrieveMultiple(query: query);
var table = new ConsoleTables.ConsoleTable("classificationcode", "whocreated", "whencreated", "name");
foreach (var entity in entityCollection.Entities)
{
var code = ((OptionSetValue)entity.GetAttributeValue<AliasedValue>("classificationcode").Value).Value;
var whocreated = ((EntityReference)entity.GetAttributeValue<AliasedValue>("whocreated").Value).Name;
var whencreated = entity.GetAttributeValue<AliasedValue>("whencreated").Value;
var companyname = entity.GetAttributeValue<string>("name");
table.AddRow(code, whocreated, whencreated, companyname);
}
table.Write();
}
Salida:
----------------------------------------------------------------------------------
| code | whocreated | whencreated | companyname |
----------------------------------------------------------------------------------
| 1 | FirstName LastName | 8/13/2023 10:30:08 PM | Fourth Coffee (sample) |
----------------------------------------------------------------------------------
| 1 | FirstName LastName | 8/13/2023 10:30:10 PM | Litware, Inc. (sample) |
----------------------------------------------------------------------------------
| 1 | FirstName LastName | 8/13/2023 10:30:10 PM | Adventure Works (sample) |
----------------------------------------------------------------------------------
La clase AliasedValue tiene dos propiedades que le indican el EntityLogicalName original y AttributeLogicalName si los necesita.
Ejemplo de valores con alias y formato aplicado
Las columnas que usan un alias devuelven un alias AliasedValue. Como se explica en Valores con formato de Access, para algunos tipos de columna, los valores de cadena con formato también se devuelven mediante la colección Entity.FormattedValues para proporcionar valores de cadena adecuados para mostrarlos en una aplicación.
El siguiente método de ejemplo estático OutputQueryExpression muestra cómo extraer valores de cadena para cada fila de datos. Esta función usa los QueryExpression.ColumnSet datos para saber qué columnas se solicitan y, a continuación, procesa los resultados para encontrar la mejor manera de mostrar los datos de registro en una aplicación, en este caso, una aplicación de consola mediante el paquete NuGet ConsoleTables para representar una tabla.
/// <summary>
/// Renders the output of a query in a table for a console application
/// </summary>
/// <param name="service">The authenticated IOrganizationService instance to use.</param>
/// <param name="query">The query to use</param>
/// <exception cref="Exception">
/// OutputQueryExpression requires all LinkEntity instances that contain columns specify an EntityAlias property.
/// </exception>
static void OutputQueryExpression(IOrganizationService service, QueryExpression query)
{
//Retrieve the data
EntityCollection entityCollection = service.RetrieveMultiple(query: query);
var columns = GetQueryExpressionColumns(query);
// Create the table using https://www.nuget.org/packages/ConsoleTables/2.5.0
var table = new ConsoleTables.ConsoleTable(columns.ToArray());
// Add the rows of the table
entityCollection.Entities.ToList().ForEach(entity =>
{
table.Rows.Add(GetRowValues(columns, entity).ToArray());
});
// Write the table to the console
table.Write();
List<string> GetQueryExpressionColumns(QueryExpression query)
{
List<string> columns = new();
columns.AddRange(GetColumns(query.ColumnSet));
foreach (LinkEntity linkEntity in query.LinkEntities)
{
columns.AddRange(GetLinkEntityColumns(linkEntity));
}
return columns;
}
List<string> GetLinkEntityColumns(LinkEntity linkEntity)
{
if (string.IsNullOrWhiteSpace(linkEntity.EntityAlias))
{
if (linkEntity.Columns.Columns.Count != 0)
{
string message = "OutputQueryExpression method requires all ";
message += "LinkEntity instances that contain columns ";
message += "specify an EntityAlias property.";
throw new Exception(message);
}
}
List<string> columns = new();
columns.AddRange(GetColumns(linkEntity.Columns, linkEntity.EntityAlias));
foreach (LinkEntity le in linkEntity.LinkEntities)
{
columns.AddRange(GetColumns(le.Columns, le.EntityAlias));
}
return columns;
}
List<string> GetColumns(ColumnSet columnset, string alias = null)
{
List<string> columns = new();
foreach (string column in columnset.Columns)
{
columns.Add(string.IsNullOrWhiteSpace(alias) ? column : $"{alias}.{column}");
}
foreach (XrmAttributeExpression item in columnset.AttributeExpressions)
{
columns.Add(item.Alias ?? item.AttributeName);
}
return columns;
}
List<string> GetRowValues(List<string> columns, Entity entity)
{
List<string> values = new();
columns.ForEach(column =>
{
if (entity.Attributes.ContainsKey(column))
{
// Use the formatted value if it available
if (entity.FormattedValues.ContainsKey(column))
{
values.Add($"{entity.FormattedValues[column]}");
}
else
{
// When an alias is used, the Aliased value must be converted
if (entity.Attributes[column] is AliasedValue aliasedValue)
{
values.Add($"{aliasedValue.Value}");
}
else
{
// Use the simple attribute value
values.Add($"{entity.Attributes[column]}");
}
}
}
// Null values are not in the Attributes collection
else
{
values.Add("NULL");
}
});
return values;
}
}
Puede usar esta función para mostrar la salida de cualquier QueryExpression consulta con el único requisito de que cualquier LinkEntity usado para combinar tablas especifique un alias. Por ejemplo, la siguiente consulta incluye valores con alias y formato junto con una tabla unida.
static void OutputQueryExpressionExample(IOrganizationService service)
{
// Specify a query:
QueryExpression query = new("account")
{
TopCount = 3,
ColumnSet = new ColumnSet("name")
{
AttributeExpressions = {
new XrmAttributeExpression{
AttributeName = "accountclassificationcode",
Alias = "classificationcode"
}
}
},
LinkEntities = {
new LinkEntity()
{
LinkFromEntityName = "account",
LinkToEntityName = "contact",
LinkFromAttributeName = "primarycontactid",
LinkToAttributeName = "contactid",
JoinOperator = JoinOperator.Inner,
EntityAlias = "person",
Columns = new ColumnSet("fullname"){
AttributeExpressions = {
new XrmAttributeExpression{
AttributeName = "accountrolecode",
Alias = "role"
}
}
}
}
}
};
// Use OutputQueryExpression
OutputQueryExpression(service, query);
}
Los resultados de esta consulta pueden tener este aspecto:
----------------------------------------------------------------------------
| name | classificationcode | person.fullname | role |
----------------------------------------------------------------------------
| Fourth Coffee | Large | Susie Curtis | Influencer |
----------------------------------------------------------------------------
| Litware, Inc. | Medium | Adele Vance | Decision Maker |
----------------------------------------------------------------------------
| Adventure Works | Small | Rafel Shillo | Employee |
----------------------------------------------------------------------------
Pasos siguientes
Obtenga información sobre cómo combinar tablas.