Partage via


Joindre des tables à l’aide de QueryExpression

Utilisez la propriété QueryExpression.LinkEntities pour décrire les données des tables associées à renvoyer avec votre requête. Cette propriété contient une collection de LinkEntity instances qui décrivent :

  • Quelles lignes de table associées renvoyer
  • Sur quelles valeurs de colonne baser la jointure
  • Quelles colonnes de ces enregistrements renvoyer
  • Tous les filtres à appliquer avec la jointure

Notes

La propriété LinkEntities est en lecture seule. Vous pouvez définir LinkEntity instances à cette collection en utilisant l’initialisation d’objet ou en utilisant le Méthode QueryExpression.AddLink.

Vous pouvez aussi utiliser System.Collections.ObjectModel.Collection<T> méthodes le LinkEntities la propriété hérite.

Propriétés LinkEntity

Le tableau suivant propose des détails sur les propriétés LinkEntity :

Property Description
LinkFromEntityName Nom logique de l’entité à lier.
Pour un LinkEntity qui n’est pas imbriqué, utilisez la même valeur que la propriété QueryExpression.EntityName.
Pour un LinkEntity imbriqué dans une collection LinkEntity.LinkEntities, utilisez la valeur de LinkEntity.LinkToEntityName à partir de l’entité de lien parent.
LinkToEntityName Nom logique de l’entité à lier.
LinkFromAttributeName Nom logique de l’Attribut de l’entité à lier.
LinkToAttributeName Nom logique de l’Attribut de l’entité à lier.
JoinOperator Opérateur de jonction. Utilisez la valeur de l’un des membres de l’énumération JoinOperator . La valeur par défaut est Inner, ce qui limite les résultats aux lignes dont les valeurs correspondent dans les deux tableaux.
Les autres valeurs valides sont :
- LeftOuter Inclut les résultats de la ligne parent qui n’ont pas de valeur correspondante.
- Natural Une seule valeur des deux colonnes jointes est renvoyée si une opération de jointure égale est effectuée et que les deux valeurs sont identiques.
Ces membres considéraient comme des des JoinOperators avancés :
- Exists
- In
- MatchFirstRowUsingCrossApply
Ces membres sont utilisés pour filtrer les valeurs dans les enregistrements associés :
- All
- Any
- NotAll
- NotAny
EntityAlias Alias de la table.
Columns Colonnes à inclure pour la table. Ajoutez ces colonnes à la table jointe à l’aide de a ColumnSet. Apprenez à sélectionner des colonnes à l’aide de QueryExpression
LinkCriteria Les expressions de filtre de condition et logiques complexes qui filtrent les résultats de la requête. Découvrez comment filtrer les lignes à l’aide de QueryExpression
LinkEntities Collection de liens entre entités pouvant inclure des liens imbriqués. Jusqu’à 15 liens au total peuvent être inclus dans une requête

Notes

La signification des propriétés LinkEntity.LinkFromAttributeName et LinkEntity.LinkToAttributeName est à l’opposé de la from correspondante et to attributs dans FetchXml. En savoir plus sur l’utilisation des attributs from et to avec FetchXml

Exemple LinkEntity

La requête suivante renvoie jusqu’à cinq enregistrements des tables compte et contact en fonction des Colonne de recherche PrimaryContactId dans l’enregistrement du compte. Il s’agit d’une relation plusieurs-à-un :

QueryExpression query = new("account")
{
      TopCount = 5,
      ColumnSet = new ColumnSet("name"),
      LinkEntities = {
            new LinkEntity()
            {
                  LinkFromEntityName = "account",
                  LinkToEntityName = "contact",
                  LinkFromAttributeName = "primarycontactid",
                  LinkToAttributeName = "contactid",
                  JoinOperator = JoinOperator.Inner,
                  EntityAlias = "contact",
                  Columns = new ColumnSet("fullname")
            }
      }
};

Les résultats ressemblent à ce qui suit :

 -----------------------------------------------------------------
 | name                             | contact.fullname           |
 -----------------------------------------------------------------
 | Litware, Inc. (sample)           | Susanna Stubberod (sample) |
 -----------------------------------------------------------------
 | Adventure Works (sample)         | Nancy Anderson (sample)    |
 -----------------------------------------------------------------
 | Fabrikam, Inc. (sample)          | Maria Campbell (sample)    |
 -----------------------------------------------------------------
 | Blue Yonder Airlines (sample)    | Sidney Higa (sample)       |
 -----------------------------------------------------------------
 | City Power & Light (sample)      | Scott Konersmann (sample)  |
 -----------------------------------------------------------------

Vous pouvez composer l’intégralité de la requête à l’aide de l’initialisation d’objet comme indiqué, mais nous vous recommandons d’utiliser QueryExpression.AddLink et LinkEntity.AddLink méthodes. Ces méthodes renvoient une référence au lien créé afin que vous puissiez facilement accéder et modifier la requête au sein de la collection. Par exemple, si vous composez la requête de cette façon à l’aide de la méthode QueryExpression.AddLink :

var query = new QueryExpression("account")
{
      TopCount = 5,
      ColumnSet = new ColumnSet("name"),
};

// Link to primary contact
LinkEntity linkedPrimaryContact = query.AddLink(
      linkToEntityName: "contact",
      linkFromAttributeName: "primarycontactid",
      linkToAttributeName: "contactid",
      joinOperator: JoinOperator.Inner);

linkedPrimaryContact.EntityAlias = "primarycontact";
linkedPrimaryContact.Columns = new ColumnSet("fullname");

Vous pouvez étendre la requête à l’aide de la méthode LinkEntity.AddLink pour inclure des informations sur le utilisateur propriétaire pour le contact lié via l’ linkedPrimaryContact LinkEntity instance :

// Link to contact owning user
LinkEntity linkedContactOwner = linkedPrimaryContact.AddLink(
      linkToEntityName: "systemuser",
      linkFromAttributeName: "owninguser",
      linkToAttributeName: "systemuserid",
      joinOperator: JoinOperator.Inner);

linkedContactOwner.EntityAlias = "owner";
linkedContactOwner.Columns = new ColumnSet("fullname");

De cette façon, vous pourrez accéder plus facilement aux différentes parties de la requête pour effectuer des ajustements.

Limitations

Vous pouvez ajouter jusqu’à 15 LinkEntity instances à une requête. Chacun LinkEntity ajoute un JOIN à la requête et augmente le temps d’exécution de la requête. Cette limite sert à protéger les performances. Si vous ajoutez plus de 15 LinkEntity instances à QueryExpression.LinkEntities, vous obtenez cette erreur d’exécution :

Nom : TooManyLinkEntitiesInQuery code : 0x8004430D
Nombre : -2147204339
Message : Number of link entities in query exceeded maximum limit.

Relations plusieurs-à-un

L’ exemple précédent est une relation plusieurs-à-un dans laquelle de nombreux enregistrements de compte peuvent faire référence à un enregistrement de contact. Ces informations sont définies dans la relation plusieurs-à-un account_primary_contact du compte, qui a les valeurs suivantes :

Propriété Valeur Commentaire
SchemaName account_primary_contact Nom unique de la relation.
ReferencedEntity contact La table référencée. Le un dans plusieurs-à-un. LinkToEntityName dans l’exemple précédent.
ReferencedAttribute contactid La clé primaire de la table référencée. LinkToAttributeName dans l’exemple précédent.
ReferencingEntity account La table avec une colonne de recherche qui fait référence à l’autre table. Le plusieurs dans plusieurs-à-un. LinkFromEntityName dans l’exemple précédent.
ReferencingAttribute primarycontactid Le nom de la colonne de recherche. LinkFromAttributeName dans l’exemple précédent.
RelationshipType OneToManyRelationship Une relation un-à-plusieurs lorsqu’elle est affichée à partir de la table contact référencée (une).
Une relation plusieurs-à-un lorsqu’elle est affichée à partir de la table de référence account (plusieurs)

Récupérer les informations sur la relation

Vous pouvez utiliser d’autres outils et API pour rechercher des données de relation pour les LinkToEntityName, LinkToAttributeName, LinkFromEntityName et LinkFromAttributeName valeurs appropriées à utiliser. Pour en savoir plus, consultez :

Exemple de relations Plusieurs-à-un

Le tableau suivant présente les valeurs de relation à utiliser pour une relation plusieurs-à-un :

Property Valeur des relations Comment
LinkFromEntityName ReferencingEntity La table référencée. Le plusieurs dans plusieurs-à-un. account dans l’exemple de relations Plusieurs-à-un. Il n’existe aucun paramètre pour cette propriété dans les méthodes AddLink car elle peut être dérivée des propriétés QueryExpression.EntityName ou LinkEntity.LinkToEntityName .
LinkToEntityName ReferencedEntity La table avec une clé primaire que les autres tables référencent. Le un dans plusieurs-à-un. contact dans l’exemple de relations Plusieurs-à-un.
LinkFromAttributeName ReferencingAttribute Le nom de la colonne de recherche. primarycontactid dans l’exemple de relations Plusieurs-à-un.
LinkToAttributeName ReferencedAttribute La clé primaire de la table référencée. contactid dans l’exemple de relations Plusieurs-à-un.

Relations 1 à N (un-à-plusieurs)

Les relations plusieurs-à-un et un-à-plusieurs sont comme regarder des deux faces d’une pièce de monnaie. La relation existe entre les tables ; par conséquent, la façon dont vous l’utilisez dépend de quelle table est la table de base pour votre requête.

Notes

Si votre table de base contient la colonne de recherche, il s’agit d’une relation plusieurs-à-un. Sinon, c’est une relation un-à-plusieurs.

Vous pouvez récupérer les mêmes données que l’ exemple précédent de la table contact en utilisant la même relation, sauf à partir de la côté de la contact table. Utilisez les données de la même relation un-à-plusieurs account_primary_contact du contact, mais ajustez les valeurs pour la vue différente de la relation.

var query = new QueryExpression("contact")
{
      TopCount = 5,
      ColumnSet = new ColumnSet("fullname"),
};

// Link to related account
var linkedPrimaryContact = query.AddLink(
      linkToEntityName: "account",
      linkFromAttributeName: "contactid",
      linkToAttributeName: "primarycontactid",
      joinOperator: JoinOperator.Inner);

linkedPrimaryContact.EntityAlias = "account";
linkedPrimaryContact.Columns = new ColumnSet("name");

Pour une relation de type un à plusieurs utilisez les valeurs de relation :

Property Valeur des relations Comment
LinkFromEntityName ReferencedEntity La table référencée. Le un dans plusieurs-à-un. contact dans l’exemple de relations un-à-Plusieurs. Il n’existe aucun paramètre pour cette propriété dans les méthodes AddLink car elle peut être dérivée des propriétés QueryExpression.EntityName ou LinkEntity.LinkToEntityName .
LinkToEntityName ReferencingEntity La table avec une colonne de recherche qui fait référence à l’autre table. Le plusieurs dans plusieurs-à-un. account dans l’exemple de relations un-à-Plusieurs.
LinkFromAttributeName ReferencedAttribute La clé primaire de la table référencée. contactid dans l’exemple de relations un-à-Plusieurs.
LinkToAttributeName ReferencingAttribute Le nom de la colonne de recherche. primarycontactid dans l’exemple de relations un-à-Plusieurs.

Les résultats incluent les mêmes enregistrements et données que l’ exemple précédent utilisant la relation plusieurs-à-un, sauf maintenant l’ entité parent’ est maintenant contact au lieu de account.

 -----------------------------------------------------------------
 | fullname                   | account.name                     |
 -----------------------------------------------------------------
 | Susanna Stubberod (sample) | Litware, Inc. (sample)           |
 -----------------------------------------------------------------
 | Nancy Anderson (sample)    | Adventure Works (sample)         |
 -----------------------------------------------------------------
 | Maria Campbell (sample)    | Fabrikam, Inc. (sample)          |
 -----------------------------------------------------------------
 | Sidney Higa (sample)       | Blue Yonder Airlines (sample)    |
 -----------------------------------------------------------------
 | Scott Konersmann (sample)  | City Power & Light (sample)      |
 -----------------------------------------------------------------

Relations plusieurs-à-plusieurs

Les relations plusieurs-à-plusieurs dépendent d’une table d’intersection. Une table d’intersection ne comporte généralement que quatre colonnes, mais seules deux d’entre elles sont importantes. Les deux colonnes importantes correspondent aux colonnes de la clé primaire des tables participantes.

Par exemple, la table d’intersection TeamMembership prend en charge la relation plusieurs-à-plusieurs teammembership_association entre les tables SystemUser et Team. Elle permet aux utilisateurs de joindre plusieurs équipes et aux équipes d’avoir plusieurs utilisateurs. TeamMembership comporte ces colonnes : systemuserid, teamid.

Si vous souhaitez récupérer des informations sur les utilisateurs et les équipes auxquelles ils appartiennent à l’aide de la teammembership_association relation plusieurs-à-plusieurs, vous pouvez utiliser cette QueryExpression requête. :

var query = new QueryExpression("systemuser")
{
      TopCount = 2,
      ColumnSet = new ColumnSet("fullname"),
};

LinkEntity linkedTeamMemberShip = query.AddLink(
      linkToEntityName: "teammembership",
      linkFromAttributeName: "systemuserid",
      linkToAttributeName: "systemuserid");

LinkEntity linkedTeam = linkedTeamMemberShip.AddLink(
      linkToEntityName: "team",
      linkFromAttributeName: "teamid",
      linkToAttributeName: "teamid");

linkedTeam.EntityAlias = "team";
linkedTeam.Columns = new ColumnSet("name");

Il existe deux LinkEntity instances.

  • linkedTeamMemberShip se connecte systemuser à la teammembership table d’intersection où systemuserid = systemuserid.
  • linkedTeam se connecte teammembership à la table d’intersection vers l’équipe où teamid = teamid.

Les résultats devraient ressembler à ce qui suit :

 --------------------------------------
 | fullname             | team.name   |
 --------------------------------------
 | FirstName LastName   | org26ed931d |
 --------------------------------------
 | # PpdfCDSClient      | org26ed931d |
 --------------------------------------

Aucune relation

Il est possible de spécifier LinkFromAttributeName et LinkToAttributeName des propriétés à l’aide de colonnes qui ne font pas partie d’une relation définie.

Par exemple, cette requête recherche des paires d’enregistrements dans lesquels la colonne Name d’un enregistrement de compte correspond à la Colonne FullName d’un enregistrement de contact, qu’ils se référencent ou non dans l’une des colonnes de recherche.

var query = new QueryExpression("account")
{
      ColumnSet = new ColumnSet("name"),
};

LinkEntity linkedContact = query.AddLink(
      linkToEntityName: "contact", 
      linkFromAttributeName: "name", 
      linkToAttributeName: "fullname");
linkedContact.EntityAlias = "contact";
linkedContact.Columns = new ColumnSet("fullname");

Notes

Il est important que les colonnes spécifiées dans les propriétés LinkFromAttributeName et LinkToAttributeName sont du même type même si elles ne sont pas impliquées dans une relation. L’utilisation de colonnes de types différents nécessitera une conversion de type qui pourrait avoir un impact sur les performances et pourrait échouer pour certaines valeurs de colonne.

Les types de colonnes ne peuvent pas être utilisés dans LinkFromAttributeName et LinkToAttributeName propriétés :

  • Fichier
  • Image
  • Champ à sélection multiple
  • PartyList

Certaines colonnes peuvent être utilisées dans les propriétés LinkFromAttributeName et LinkToAttributeName , mais peuvent entraîner de mauvaises performances :

  • Colonnes de type Plusieurs lignes de texte
  • Colonnes de type Une seule ligne de texte d’une longueur maximale supérieure à 850
  • Colonnes de formule
  • Colonnes calculées
  • Colonnes logiques

Rechercher des enregistrements qui ne font pas partie d’un ensemble

Vous pouvez utiliser QueryExpression pour créer une requête pour renvoyer les enregistrements qui ne font pas partie d’un ensemble à l’aide d’un jointure externe gauche. Une jointure externe gauche renvoie chaque ligne qui répond à la jointure de la première entrée avec la seconde entrée. Elle renvoie également toute ligne de la première entrée qui n’avait pas de lignes correspondantes dans la seconde entrée. Les lignes sans correspondance de la seconde entrée sont renvoyées comme valeurs nulles.

Vous pouvez effectuer une jointure externe gauche dans QueryExpression en utilisant la propriété ConditionExpression.EntityName. La propriété EntityName est valide en termes de conditions, de filtres et de filtres imbriqués. En savoir plus sur les filtres sur LinkEntity

Par exemple, la requête suivante renvoie tous les enregistrements de contact sans contacts.

var query = new QueryExpression(entityName: "account");
query.ColumnSet.AddColumn("name");
query.AddOrder(
      attributeName: "name", 
      orderType: OrderType.Descending);
query.Criteria.AddCondition(
      entityName: "contact",
      attributeName: "parentcustomerid",
      conditionOperator: ConditionOperator.Null);

LinkEntity linkedContact = query.AddLink(
      linkToEntityName: "contact",
      linkFromAttributeName: "accountid",
      linkToAttributeName: "parentcustomerid",
      joinOperator: JoinOperator.LeftOuter);
linkedContact.EntityAlias = "contact";
linkedContact.Columns.AddColumn("fullname");

Utiliser les JoinOperators avancés

Ce qui suit Membres JoinOperator ne correspondent pas directement à T-SQL Opérateur REJOINDRE types et utilisation sous-requêtes plutôt. Ces types offrent des fonctionnalités plus avancées que vous pouvez utiliser pour améliorer les performances des requêtes et définir des requêtes plus complexes.

Nom Description
Exists Une variante de Inner qui peut offrir des avantages en termes de performances. Utilise une condition EXISTS dans la clause where. Utiliser Exists lorsque plusieurs copies de la ligne parent ne sont pas nécessaires dans les résultats. En savoir plus sur Exists et In.
In Une variante de Inner qui peut offrir des avantages en termes de performances. Utilise un DANS condition dans la clause Where. Utiliser In lorsque plusieurs copies de la ligne parent ne sont pas nécessaires dans les résultats. En savoir plus sur Exists et In.
MatchFirstRowUsingCrossApply Une variante de Inner qui peut offrir des avantages en termes de performances. Utilisez ce type lorsqu’un seul exemple de ligne correspondante de l’entité liée est suffisant et que plusieurs copies de la ligne parente dans les résultats ne sont pas nécessaires. En savoir plus sur l’utilisation de MatchFirstRowUsingCrossApply

Utilisez JoinOperator.Exists ou JoinOperator.In

Exists et In sont des variantes de Inner qui utilisent différentes conditions (EXISTS et IN respectivement) dans la clause where afin que plusieurs copies de la ligne parente ne soient pas renvoyées dans les résultats. Les deux Exists et In ne renvoie pas les valeurs de colonne des lignes d’entité associées.

En utilisant JoinOperator.Exists ou JoinOperator.In peut réduire la taille des résultats de requête intermédiaires ou finaux, en particulier lorsqu’il existe de nombreuses lignes liées correspondantes pour les mêmes lignes parent, ou lorsque plusieurs entités de lien sont utilisées avec le même parent. En utilisant JoinOperator.Exists ou JoinOperator.In peut améliorer les performances de la requête par rapport à JoinOperator.Inner car il ne nécessite pas de renvoyer un produit cartésien contenant toutes les permutations possibles de lignes de différentes entités liées pour chaque ligne parent.

Ces JoinOperator membres peuvent également permettre Dataverse de trouver uniquement la première ligne d’entité liée correspondante pour chaque ligne parent, ce qui est plus efficace que de rechercher toutes les lignes correspondantes dans l’entité liée avec JoinOperator.Inner.

Exemple avec JoinOperator.Exists

Ces exemples QueryExpression et SQL montrent les modèles appliqués avec JoinOperator.Exists.

QueryExpression query = new("contact");
query.ColumnSet.AddColumn("fullname");

LinkEntity linkedAccount = query.AddLink(
      linkToEntityName: "account",
      linkFromAttributeName: "contactid",
      linkToAttributeName: "primarycontactid",
      joinOperator: JoinOperator.Exists);

linkedAccount.EntityAlias = "account";

linkedAccount.LinkCriteria.AddCondition(
      entityName:"account", 
      attributeName: "statecode", 
      conditionOperator: ConditionOperator.Equal,
      values: 1);

Exemple avec JoinOperator.In

Ces exemples QueryExpression et SQL montrent les modèles appliqués avec JoinOperator.In.

QueryExpression query = new("contact");
query.ColumnSet.AddColumn("fullname");

LinkEntity linkedAccount = query.AddLink(
      linkToEntityName: "account",
      linkFromAttributeName: "contactid",
      linkToAttributeName: "primarycontactid",
      joinOperator: JoinOperator.In);

linkedAccount.EntityAlias = "account";

linkedAccount.LinkCriteria.AddCondition(
      entityName: "account",
      attributeName: "statecode",
      conditionOperator: ConditionOperator.Equal,
      values: 1);

Utiliser JoinOperator.MatchFirstRowUsingCrossApply

JoinOperator.MatchFirstRowUsingCrossApply produit un CROSS APPLY opérateur avec une sous-requête utilisant top 1 suivant ce modèle :

QueryExpression query = new("contact");
query.ColumnSet.AddColumn("fullname");

LinkEntity linkedAccount = query.AddLink(
      linkToEntityName: "account",
      linkFromAttributeName: "contactid",
      linkToAttributeName: "primarycontactid",
      joinOperator: JoinOperator.MatchFirstRowUsingCrossApply);

linkedAccount.EntityAlias = "account";
linkedAccount.Columns = new ColumnSet("accountid", "name");

Ceci est équivalent à JoinOperator.LeftOuter sauf qu’il ne renvoie la ligne parent qu’au plus une fois. Contrairement à JoinOperator.In et JoinOperator.Exists, il renvoie les valeurs de colonne de l’une des lignes correspondantes dans la table associée lorsque des lignes correspondantes existent, mais la ligne parent est renvoyée même s’il n’y a aucune ligne correspondante dans le tableau associé. Utilisez cette option lorsqu’un seul exemple de ligne correspondante de la table associée est suffisant et que plusieurs copies de la ligne parent dans les résultats ne sont pas nécessaires.

Étapes suivantes

Découvrez comment trier des lignes.

Notes

Pouvez-vous nous indiquer vos préférences de langue pour la documentation ? Répondez à un court questionnaire. (veuillez noter que ce questionnaire est en anglais)

Le questionnaire vous prendra environ sept minutes. Aucune donnée personnelle n’est collectée (déclaration de confidentialité).