Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Important
Nous déconseillons fortement de renvoyer toutes les colonnes d’un tableau avec votre requête. Le renvoi de toutes les colonnes ralentira l’exécution de vos applications et peut provoquer des erreurs de délai d’attente. Vous devez spécifier le nombre minimal de colonnes à récupérer avec vos données. Si vous définissez la propriété ColumnSet.AllColumns sur true, les données de toutes les colonnes sont retournées. Si vous ne définissez aucune colonne, seule la valeur de clé primaire de l’enregistrement est retournée. Ceci est opposé au comportement à l’aide de FetchXml, où toutes les colonnes sont retournées si vous ne spécifiez aucun.
Utilisez la classe ColumnSet pour spécifier les noms des colonnes à retourner avec votre requête. Utilisez la valeur AttributeMetadata.LogicalName pour chaque colonne. Les valeurs de nom logique sont toujours en minuscules.
Vous pouvez spécifier les colonnes avec le constructeur ColumnSet(String[]) lorsque vous initialisez :QueryExpression
QueryExpression query = new("account")
{
ColumnSet = new ColumnSet("name", "accountclassificationcode", "createdby", "createdon")
};
Vous pouvez également utiliser les méthodes ColumnSet.AddColumn ou ColumnSet.AddColumns pour ajouter des colonnes supplémentaires à la propriété QueryExpression.ColumnSet après l’initialisation QueryExpression .
QueryExpression query = new("account");
query.ColumnSet.AddColumn("name");
query.ColumnSet.AddColumns("accountclassificationcode", "createdby", "createdon");
Note
Certaines colonnes ne sont pas valides pour la lecture. La propriété AttributeMetadata.IsValidForRead indique si une colonne est valide pour la lecture. Si vous incluez les noms de ces colonnes, aucune valeur n’est retournée.
La propriété ColumnSet.Columns est une chaîne< Microsoft.Xrm.Sdk.DataCollection> qui étend la classe System.Collections.ObjectModel.Collection<T>. Vous pouvez donc également utiliser les méthodes de ces classes de base pour interagir avec les chaînes de la collection.
Sélectionner des colonnes pour les tables jointes
Lorsque vous joignez des tables à l’aide de QueryExpression, vous utilisez la classe LinkEntity. La propriété LinkEntity.Columns est un ColumnSet. Vous allez donc définir les colonnes à retourner pour les tables jointes de la même façon.
Premières classes de champs liés
Si vous utilisez des classes de champs à liaison anticipée générées à l’aide de la commande pac modelbuilder avec le commutateur emitfieldsclasses activé, vous peut utiliser les constantes générées pour tous les noms de champs plutôt que d’utiliser les noms logiques directement sous forme de chaînes.
QueryExpression query = new(Account.EntityLogicalName)
{
ColumnSet = new ColumnSet(
Account.Fields.Name,
Account.Fields.AccountClassificationCode,
Account.Fields.CreatedBy,
Account.Fields.CreatedOn)
};
Cela permet d’éviter les erreurs d’exécution en raison de la saisie du nom incorrect. Pour en savoir plus :
- Génération de classes à liaison anticipée pour le SDK pour .NET
- Programmation avec liaison tardive et anticipée à l’aide du SDK pour .NET
Alias de colonne
Les alias de colonne sont généralement utilisés pour les opérations d’agrégation, mais ils fonctionnent également pour récupérer des lignes. Nous pouvons donc les présenter ici.
Ajoutez des instances XrmAttributeExpression à la collection ColumnSet.AttributeExpressions pour spécifier un nom de colonne unique pour les résultats retournés. Pour chaque instance, définissez ces propriétés :
| Propriété | Descriptif |
|---|---|
| AttributeName | Nom logique de la colonne |
| Alias | Nom unique de la colonne à afficher dans les résultats |
| AggregateType | Quand vous n’agrègez pas de données, utilisez le membre XrmAggregateType.None . Il s’agit de la valeur par défaut. Vous n’avez donc pas besoin de la définir si vous n’utilisez pas l’agrégation.
En savoir plus sur l’agrégation de données avec QueryExpression |
Chaque colonne retournée doit avoir un nom unique. Par défaut, les noms de colonnes retournés pour la table de votre requête sont les valeurs de colonne LogicalName . Tous les noms logiques des colonnes sont uniques au sein de chaque table, ce qui empêche toute duplication de noms dans cet ensemble.
Lorsque vous utilisez un LinkEntity pour joindre des tables, vous pouvez définir la propriété EntityAlias pour la table représentée par LinkEntity. Les noms de colonnes dans la propriété LinkEntity.Columns suivent cette convention d’affectation de noms : {Linked table LogicalName or alias}.{Column LogicalName}. Cela empêche tout nom de colonne en double.
Cependant, lorsque vous spécifiez un alias de colonne à l’aide de Propriété XrmAttributeExpression.Alias, le LinkEntity.EntityAlias ou la valeur du nom logique de la table n’est pas ajoutée au début de la valeur de l’alias. Vous devez vous assurer que la valeur de l’alias est unique. Si la valeur n’est pas unique, vous pouvez vous attendre à cette erreur :
Nom :
QueryBuilderDuplicateAlias
Code :0x80041130
Nombre :-2147217104
Message :< alias value > is not a unique alias. It clashes with an autogenerated alias or user provided alias
Exemple d’alias de colonne
Cet SimpleAliasOutput exemple de méthode utilise des alias et des noms logiques des colonnes. En raison de cela, les résultats qui utilisent des alias sont retournés en tant que AliasedValue. Pour accéder à la valeur des types tels que OptionSetValue ou EntityReference, vous devez convertir la valeur.
Dans cet exemple, les alias sont spécifiés uniquement pour les colonnes accountclassificationcode, createdby, et createdon. La name colonne n’utilise pas d’alias. Cette méthode dépend du package NuGet ConsoleTables pour afficher la table.
/// <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();
}
Sortie:
----------------------------------------------------------------------------------
| 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 classe AliasedValue a deux propriétés qui vous indiquent l’EntityLogicalName d’origine et AttributeLogicalName si vous en avez besoin.
Exemple de valeurs déguisées et mises en forme
Les colonnes qui utilisent un alias retournent un AliasedValue. Comme expliqué dans les valeurs mises en forme Access, pour certains types de colonnes, les valeurs de chaîne mises en forme sont également retournées à l’aide de la collection Entity.FormattedValues pour fournir des valeurs de chaîne adaptées à l’affichage dans une application.
L’exemple de méthode statique OutputQueryExpression suivant montre comment extraire des valeurs de chaîne pour chaque ligne de données. Cette fonction utilise les QueryExpression.ColumnSet données pour savoir quelles colonnes sont demandées, puis traite les résultats pour trouver le meilleur moyen d’afficher les données d’enregistrement dans une application, dans ce cas, une application console utilisant le package NuGet ConsoleTables pour afficher une table.
/// <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;
}
}
Vous pouvez utiliser cette fonction pour afficher la sortie d’une QueryExpression requête avec la seule exigence que toute LinkEntity utilisée pour joindre des tables spécifie un alias. Par exemple, la requête suivante inclut des valeurs avec des alias et formatées avec une table jointe :
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);
}
Les résultats de cette requête peuvent ressembler à ceci :
----------------------------------------------------------------------------
| name | classificationcode | person.fullname | role |
----------------------------------------------------------------------------
| Fourth Coffee | Large | Susie Curtis | Influencer |
----------------------------------------------------------------------------
| Litware, Inc. | Medium | Adele Vance | Decision Maker |
----------------------------------------------------------------------------
| Adventure Works | Small | Rafel Shillo | Employee |
----------------------------------------------------------------------------
Étapes suivantes
Découvrez comment associer des tables de données.