Compartir a través de


Unir tablas usando QueryExpression

Utilice la propiedad QueryExpression.LinkEntities para describir los datos de las tablas relacionadas que se devolverán con su consulta. Esta propiedad contiene una colección de instancias de LinkEntity que describen:

  • Qué filas de la tabla relacionadas devolver
  • En qué valores de columna basar la combinación
  • Qué columnas de esos registros devolver
  • Cualquier filtro para aplicar con la combinación

Nota

La propiedad LinkEntities es de solo lectura. Puede configurar instancias de LinkEntity en esta colección usando la inicialización de objetos o usando el método QueryExpression.AddLink.

También puede usar métodos System.Collections.ObjectModel.Collection<T> las herencias de propiedades de LinkEntities.

Propiedades de LinkEntity

La siguiente tabla proporciona detalles sobre las propiedades de LinkEntity:

Property Description
LinkFromEntityName El nombre lógico de la entidad desde la que se está vinculando.
Para LinkEntity que no está anidado, use el mismo valor que la propiedad QueryExpression.EntityName.
Para un LinkEntity que está anidado en una colección LinkEntity.LinkEntities, use el valor de LinkEntity.LinkToEntityName de la entidad de vínculo principal.
LinkToEntityName El nombre lógico de la entidad a la que se está vinculando.
LinkFromAttributeName El nombre lógico del atributo de la entidad desde la que se está vinculando.
LinkToAttributeName El nombre lógico del atributo de la entidad a la que se está vinculando.
JoinOperator El operador de combinación. Utilice un valor de uno de los miembros de JoinOperator enum. El valor predeterminado es Inner, que restringe los resultados a filas con valores coincidentes en ambas tablas.
Otros valores válidos son:
- LeftOuter incluye resultados de la fila principal que no tienen un valor coincidente.
- Natural Solo se devuelve un valor de las dos columnas unidas si se realiza una operación de combinación igual y los dos valores son idénticos.
Estos miembros consideraron JoinOperators avanzados:
- Exists
- In
- MatchFirstRowUsingCrossApply
Estos miembros se utilizan para filtrar valores en registros relacionados:
- All
- Any
- NotAll
- NotAny
EntityAlias El alias de la tabla.
Columns Las columnas que se incluirán en la tabla. Agregue estas columnas a la tabla unida usando ColumnSet. Aprenda a seleccionar columnas usando QueryExpression
LinkCriteria La condición compleja y las expresiones de filtro lógicas que filtran los resultados de la consulta. Aprender a filtrar filas usando QueryExpression
LinkEntities La colección de vínculos entre entidades que pueden incluir vínculos anidados. Se pueden incluir hasta 15 vínculos en total en una consulta.

Nota

El significado de las propiedades LinkEntity.LinkFromAttributeName y LinkEntity.LinkToAttributeName es el opuesto de sus atributos from y to correspondientes en FetchXml. Obtener más información sobre el uso de los atributos from y to con FetchXml

Ejemplo de LinkEntity

La siguiente consulta devuelve hasta cinco registros de las tablas cuenta y contacto basadas en la columna de búsqueda PrimaryContactId en el registro de cuenta. Esto representa una relación de varios a uno:

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")
            }
      }
};

Los resultados tienen este aspecto:

 -----------------------------------------------------------------
 | 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)  |
 -----------------------------------------------------------------

Puede redactar la consulta completa utilizando la inicialización de objetos como se muestra, pero recomendamos usar los métodos QueryExpression.AddLink y LinkEntity.AddLink. Estos métodos devuelven una referencia al vínculo creado para que pueda tener acceso y modificar fácilmente la consulta dentro de la colección. Por ejemplo, si redacta la consulta de esta manera utilizando el método 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");

Puede ampliar la consulta utilizando el método LinkEntity.AddLink para incluir información sobre usuario propietario para el contacto vinculado a través de la instancia linkedPrimaryContact LinkEntity:

// 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 esta manera podrá tener acceso más fácilmente a las diferentes partes de la consulta para realizar ajustes.

Limitaciones

Puede agregar hasta 15 instancias LinkEntity a una consulta. Cada LinkEntity agrega un JOIN a la consulta y aumenta el tiempo para ejecutar la consulta. Este límite es para proteger el rendimiento. Si agrega más de 15 instancias de LinkEntity a QueryExpression.LinkEntities, obtendrá este error de tiempo de ejecución:

Nombre: TooManyLinkEntitiesInQuery Código: 0x8004430D
Número: -2147204339
Mensaje: Number of link entities in query exceeded maximum limit.

Relaciones de varios a uno

El ejemplo anterior es una relación de muchos a uno donde muchos registros de cuentas pueden hacer referencia a un registro de contacto. Esta información se define en la relación de muchos a uno Relación de cuenta account_primary_contact, que tiene los siguientes valores:

Propiedad valor Comentario
SchemaName account_primary_contact Nombre único de la relación.
ReferencedEntity contact La tabla referenciada. El one (uno) en many-to-one (muchos a uno). LinkToEntityName en el ejemplo anterior.
ReferencedAttribute contactid La clave principal de la tabla referenciada. LinkToAttributeName en el ejemplo anterior.
ReferencingEntity account La tabla con una columna de búsqueda que hace referencia a la otra tabla. El many (muchos) en many-to-one (muchos a uno). LinkFromEntityName en el ejemplo anterior.
ReferencingAttribute primarycontactid El nombre de la columna de búsqueda. LinkFromAttributeName en el ejemplo anterior.
RelationshipType OneToManyRelationship Una relación de uno a muchos cuando se ve desde la tabla referenciada (uno) contact.
Una relación de muchos a uno cuando se be desde la tabla de referencia (muchos) account

Recuperar información de la relación

Puede utilizar otras herramientas y API para buscar datos de relaciones para los valores LinkToEntityName, LinkToAttributeName, LinkFromEntityName y LinkFromAttributeName a utilizar. Para obtener más información, consulte:

Ejemplo de relación varios a uno

La siguiente tabla muestra los valores de relación que se utilizarán para una relación de varios a uno:

Property Valor de la relación Comment
LinkFromEntityName ReferencingEntity La tabla referenciada. El many (muchos) en many-to-one (muchos a uno). account en el ejemplo de varios a uno. No hay ningún parámetro para esta propiedad en los métodos AddLink porque puede derivarse de las propiedades QueryExpression.EntityName o LinkEntity.LinkToEntityName.
LinkToEntityName ReferencedEntity La tabla con una clave principal a la que hace referencia la otra tabla. El one (uno) en many-to-one (muchos a uno). contact en el ejemplo de varios a uno.
LinkFromAttributeName ReferencingAttribute El nombre de la columna de búsqueda. primarycontactid en el ejemplo de varios a uno.
LinkToAttributeName ReferencedAttribute La clave principal de la tabla referenciada. contactid en el ejemplo de varios a uno.

Relaciones de uno a varios

Las relaciones de muchos a uno y de uno a muchos son como ver las dos caras de una moneda. La relación existe entre las tablas, por lo que la forma en que la use depende de qué tabla es la tabla base para su consulta.

Nota

Si su tabla base contiene la columna de búsqueda, es una relación de varios a uno. De lo contrario, es una relación de uno a varios.

Puede recuperar los mismos datos que en el ejemplo anterior de la tabla contacto usando la misma relación, excepto en la lado de la tabla contact. Utilice los datos de la misma relación de cuenta account_primary_contact one-to-many, pero ajuste los valores para la vista diferente de la relación.

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");

Para una relación de uno a varios, utilice estos valores de relación:

Property Valor de la relación Comment
LinkFromEntityName ReferencedEntity La tabla referenciada. El one (uno) en many-to-one (muchos a uno). contact en el ejemplo de uno a varios. No hay ningún parámetro para esta propiedad en los métodos AddLink porque puede derivarse de las propiedades QueryExpression.EntityName o LinkEntity.LinkToEntityName.
LinkToEntityName ReferencingEntity La tabla con una columna de búsqueda que hace referencia a la otra tabla. El many (muchos) en many-to-one (muchos a uno). account en el ejemplo de uno a varios.
LinkFromAttributeName ReferencedAttribute La clave principal de la tabla referenciada. contactid en el ejemplo de uno a varios.
LinkToAttributeName ReferencingAttribute El nombre de la columna de búsqueda. primarycontactid en el ejemplo de uno a varios.

Los resultados incluyen los mismos registros y datos que el ejemplo anterior usando la relación de varios a uno, excepto que ahora la 'entidad principal' es contact en lugar 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)      |
 -----------------------------------------------------------------

Relaciones de varios a varios

Las relaciones de muchos a muchos dependen de una tabla de intersección. Una tabla de intersección normalmente tiene solo cuatro columnas, pero solo dos de ellas son importantes. Las dos columnas importantes coinciden con las columnas de clave principal de las tablas participantes.

Por ejemplo, la tabla de intersección TeamMembership admite la relación de muchos a muchos teammembership_association entre SystemUser y Team . Permite a los usuarios unirse a varios equipos y a los equipos tener varios usuarios. TeamMembership tiene estas columnas: systemuserid, teamid.

Si desea recuperar información sobre los usuarios y los equipos a los que pertenecen utilizando la relación teammembership_association de varios a varios, puede utilizar esta consulta QueryExpression:

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");

Hay dos instancias de LinkEntity.

  • linkedTeamMemberShip se conecta systemuser a la tabla de intersección de teammembership donde systemuserid = systemuserid.
  • linkedTeam conecta la tabla de intersección de teammembership al equipo en el que teamid = teamid.

El resultado deberá ser ahora similar a:

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

No existe relación

Es posible especificar propiedades LinkFromAttributeName y LinkToAttributeName usando columnas que no forman parte de una relación definida.

Por ejemplo, esta consulta encuentra pares de registros donde la Columna de nombre de un registro de cuenta coincide con la columna FullName de un registro de contacto independientemente de si se hacen referencia entre sí en cualquiera de las columnas de búsqueda.

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");

Nota

Es importante que las columnas especificadas en las propiedades LinkFromAttributeName y LinkToAttributeName sean del mismo tipo incluso si no están involucradas en una relación. El uso de columnas de diferentes tipos requerirá una conversión de tipo que podría tener un impacto en el rendimiento y podría fallar en algunos valores de columna.

Los siguientes tipos de columnas no se pueden usar en las propiedades LinkFromAttributeName y LinkToAttributeName:

Algunas columnas se pueden utilizar en las propiedades LinkFromAttributeName y LinkToAttributeName, pero pueden provocar un rendimiento deficiente:

  • Columnas del tipo Varias líneas de texto
  • Columnas del tipo Línea única de texto con una longitud máxima superior a 850
  • Columnas de Fórmula
  • Columnas de Calculado
  • Columnas Lógicas

Buscar registros que no estén en un conjunto

Puede usar QueryExpression para crear una consulta para devolver registros que no están en un conjunto usando una combinación externa izquierda. Una combinación externa izquierda devuelve todas las filas que satisfacen la combinación de la primera entrada con la segunda entrada. También devuelve las filas de la primera entrada que no tenían ninguna fila coincidente en la segunda entrada. Las filas no coincidentes de la segunda entrada se devuelven como valores nulos.

Puede realizar una combinación externa izquierda en QueryExpression usando la propiedad ConditionExpression.EntityName. La propiedad EntityName es válida en condiciones, filtros y filtros anidados. Obtener más información sobre los filtros en LinkEntity

Por ejemplo, la siguiente consulta devuelve todos los registros de cuentas sin contactos.

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");

Usar JoinOperators avanzados

Los siguientes miembros JoinOperator no corresponden directamente a tipos operador JOIN de T-SQL y usan subconsultas en su lugar. Estos tipos proporcionan capacidades más avanzadas que puede utilizar para mejorar el rendimiento de las consultas y definir consultas más complejas.

Name Description
Exists Una variante de Inner que pueden proporcionar beneficios de rendimiento. Utiliza una condición EXISTS en la cláusula where . Use Exists cuando no sean necesarias varias copias de la fila principal en los resultados. Obtener más información sobre Exists y In.
In Una variante de Inner que pueden proporcionar beneficios de rendimiento. Utiliza una condición IN en la cláusula where. Use In cuando no sean necesarias varias copias de la fila principal en los resultados. Obtener más información sobre Exists y In.
MatchFirstRowUsingCrossApply Una variante de Inner que pueden proporcionar beneficios de rendimiento. Utilice este tipo cuando solo sea suficiente un único ejemplo de una fila coincidente de la entidad vinculada y no sean necesarias varias copias de la fila principal en los resultados. Obtener más información sobre el uso de MatchFirstRowUsingCrossApply

Use JoinOperator.Exists o JoinOperator.In

Exists e In son variantes de Inner que utilizan diferentes condiciones ( EXISTS e IN respectivamente) en la cláusula where para que no se devuelvan varias copias de la fila principal en los resultados. Exists y In no devuelven los valores de las columnas de las filas de la entidad relacionada.

El uso de JoinOperator.Exists o JoinOperator.In puede reducir el tamaño de los resultados de la consulta intermedia o final, especialmente cuando existen muchas filas vinculadas coincidentes para las mismas filas principales, o cuando se utilizan varias entidades de vínculo con el mismo padre. El uso de JoinOperator.Exists o JoinOperator.In puede mejorar el rendimiento de la consulta en comparación con JoinOperator.Inner porque no requiere devolver un producto cartesiano que contenga todas las permutaciones posibles de filas de diferentes entidades vinculadas para cada fila principal.

Estos miembros de JoinOperator también podrían permitir a Dataverse buscar solo la primera fila de entidad vinculada coincidente para cada fila principal, lo cual es más eficiente que buscar todas las filas coincidentes en la entidad vinculada con JoinOperator.Inner.

Ejemplo de JoinOperator.Exists

Estos ejemplos de QueryExpression y SQL muestran los patrones aplicados con 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);

Ejemplo de JoinOperator.In

Estos ejemplos de QueryExpression y SQL muestran los patrones aplicados con 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);

Usar JoinOperator.MatchFirstRowUsingCrossApply

JoinOperator.MatchFirstRowUsingCrossApply produce un operador CROSS APPLY con una subconsulta usando top 1 siguiendo este patrón:

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");

Esto es equivalente a JoinOperator.LeftOuter excepto que solo devuelve la fila principal como máximo una vez. A diferencia de JoinOperator.In y JoinOperator.Exists, devuelve valores de columna de una de las filas coincidentes en la tabla relacionada cuando existen filas coincidentes, pero la fila principal se devuelve incluso si no hay filas coincidentes en la tabla relacionada. Utilícelo cuando solo sea suficiente un único ejemplo de una fila coincidente de la tabla relacionada y no sean necesarias varias copias de la fila principal en los resultados.

Pasos siguientes

Aprenda a filtrar las filas de pedidos.

Nota

¿Puede indicarnos sus preferencias de idioma de documentación? Realice una breve encuesta. (tenga en cuenta que esta encuesta está en inglés)

La encuesta durará unos siete minutos. No se recopilan datos personales (declaración de privacidad).