Procesamiento por lotes | Conceptos de Graph API

Se aplica a: Graph API | Azure Active Directory (AD)

Con la API de Azure AD Graph, puede procesar operaciones por lotes en entidades para reducir los ciclos de ida y vuelta al servidor. Con el procesamiento por lotes de las solicitudes se reduce la sobrecarga de la red y las operaciones finalizarán más rápidamente.

Importante

Se recomienda encarecidamente que use Microsoft Graph en lugar de la API de Azure AD Graph para acceder a recursos de Azure Active Directory. Nuestros esfuerzos de desarrollo se concentran ahora en Microsoft Graph y no están previstas mejoras adicionales para la API de Azure AD Graph. Hay un número muy limitado de escenarios para los que la API de Azure AD Graph todavía podría ser adecuada; para más información, vea la entrada del blog Microsoft Graph o Azure AD Graph en el centro de desarrollo de Office. Tenga en cuenta que el procesamiento por lotes no se admite actualmente en Microsoft Graph; debe usar la API de Azure AD Graph para esta característica.

Compatibilidad con Graph API para solicitudes por lotes de OData

La semántica para el procesamiento por lotes de entidades se define mediante la especificación del procesamiento por lotes de OData 3.0. La especificación OData define los siguientes conceptos para solicitudes de lotes:

  • Una consulta es una invocación de consulta o de función única.
  • Un conjunto de cambios es un grupo de una o varias operaciones de inserción, actualización o eliminación, invocaciones de acción o de servicio.
  • Un lote es un contenedor de operaciones, que incluye uno o varios conjuntos de cambios y operaciones de consulta.

Graph API admite un subconjunto de funcionalidad definido por la especificación OData:

  • Un único lote puede contener un máximo de cinco consultas y/o conjuntos de cambios combinados.
  • Un conjunto de cambios puede contener un máximo de una modificación de objetos de origen y hasta 20 operaciones de agregar vínculo y eliminar vínculo combinadas. Todas las operaciones del conjunto de cambios deben estar en una entidad de origen único.

Solicitudes por lotes de Graph API

En las secciones siguientes se describe cómo construir una solicitud por lotes, cómo interpretar la respuesta por lotes e incluye ejemplos de cada una de las operaciones.

Sintaxis de la solicitud por lotes

Para realizar una solicitud por lotes, especifique la opción $batch en el URI de solicitud. Por ejemplo:

https://graph.windows.net/contoso.onmicrosoft.com/$batch?api-version=1.6

Se envía una solicitud por lotes al servidor con una única directiva POST.

La carga es un mensaje MIME de varias partes que contiene el lote, así como sus consultas y conjuntos de cambios constituyentes. La carga incluye dos tipos de límites MIME:

  • Un límite de lote separa cada consulta y/o conjunto de cambios del lote.
  • Un límite de conjunto de cambios separa las operaciones individuales dentro de un conjunto de cambios.

Una solicitud individual del conjunto de cambios es idéntica a una solicitud que se realice cuando esa operación se llama a sí misma. Por ejemplo:

  • Para especificar el formato de carga (JSON o ATOM) para cada operación del conjunto de cambios, incluya encabezados Content-Type y, si es necesario, Accept adecuados.
  • Para suprimir el eco del contenido de respuesta al crear una entidad, especifique el encabezado Prefer con el valor return-no-content para cada operación de inserción en un conjunto de cambios.

Solicitud de ejemplo

En el ejemplo siguiente se muestra una solicitud por lotes que contiene cinco elementos:

  1. Un conjunto de cambios que crea un usuario, testuser@contoso.onmicrosoft.com (POST). Esta operación incluye el encabezado Prefer: response-no-content para suprimir el usuario recién creado que se va a devolver.
  2. Un conjunto de cambios que actualiza las propiedades del departamento y del puesto del nuevo usuario (PATCH) y establece su propiedad de navegación del administrador (PUT).
  3. Una consulta para el administrador del nuevo usuario (GET).
  4. Un conjunto de cambios que elimina el nuevo usuario (DELETE).
  5. Una consulta para el usuario (GET). Se producirá un error en esta operación porque se eliminó el usuario en el paso anterior.
POST https://graph.windows.net/contoso.onmicrosoft.com/$batch?api-version=1.5 HTTP/1.1
Authorization: Bearer ey … jQA
Content-Type: multipart/mixed; boundary=batch_36522ad7-fc75-4b56-8c71-56071383e77b 
Host: graph.windows.net
Content-Length: 2961

--batch_36522ad7-fc75-4b56-8c71-56071383e77b 
Content-Type: multipart/mixed; boundary=changeset_77162fcd-b8da-41ac-a9f8-9357efbbd620 
Content-Length: 631       

--changeset_77162fcd-b8da-41ac-a9f8-9357efbbd620 
Content-Type: application/http 
Content-Transfer-Encoding: binary 

POST /contoso.onmicrosoft.com/users?api-version=1.5 HTTP/1.1
Content-Type: application/json
Accept: application/json
Content-Length: 256
Prefer: return-no-content
Host: graph.windows.net

{
    "accountEnabled": true,
    "displayName": "Test User",
    "mailNickname": "testuser",
    "passwordProfile": { "password" : "Test1234", "forceChangePasswordNextLogin": false },
    "userPrincipalName": "testuser@contoso.onmicrosoft.com"
}

--changeset_77162fcd-b8da-41ac-a9f8-9357efbbd620----batch_36522ad7-fc75-4b56-8c71-56071383e77b 
Content-Type: multipart/mixed; boundary=changeset_4b2cbfb7-011d-4edb-8bbf-e044f9830aaf 
Content-Length: 909

--changeset_4b2cbfb7-011d-4edb-8bbf-e044f9830aaf 
Content-Type: application/http 
Content-Transfer-Encoding: binary 

PATCH /contoso.onmicrosoft.com/users/testuser@contoso.onmicrosoft.com?api-version=1.5 HTTP/1.1
Content-Type: application/json
Accept: application/json
Content-Length: 72
Host: graph.windows.net

{
    "department": "Engineering",
    "jobTitle": "Test Engineer"
}

--changeset_4b2cbfb7-011d-4edb-8bbf-e044f9830aaf 
Content-Type: application/http 
Content-Transfer-Encoding: binary 

PUT /contoso.onmicrosoft.com/users/testuser@contoso.onmicrosoft.com/$links/manager?api-version=1.5 HTTP/1.1
Content-Type: application/json
Accept: application/json
Content-Length: 112
Host: graph.windows.net

{
  "url":"https://graph.windows.net/contoso.onmicrosoft.com/users/a71e4d1c-ce99-40dc-8d4b-390eac63e039"
}

--changeset_4b2cbfb7-011d-4edb-8bbf-e044f9830aaf----batch_36522ad7-fc75-4b56-8c71-56071383e77b 
Content-Type: application/http 
Content-Transfer-Encoding:binary

GET /contoso.onmicrosoft.com/users/testuser@contoso.onmicrosoft.com/$links/manager?api-version=1.5 HTTP/1.1
Accept: application/json
Host: graph.windows.net

--batch_36522ad7-fc75-4b56-8c71-56071383e77b 
Content-Type: multipart/mixed; boundary=changeset_9a0b5878-0f4a-4f57-91c5-9792cdd5ef20 
Content-Length: 331       

--changeset_9a0b5878-0f4a-4f57-91c5-9792cdd5ef20 
Content-Type: application/http 
Content-Transfer-Encoding: binary 

DELETE /contoso.onmicrosoft.com/users/testuser@contoso.onmicrosoft.com?api-version=1.5 HTTP/1.1
Accept: application/json
Host: graph.windows.net


--changeset_9a0b5878-0f4a-4f57-91c5-9792cdd5ef20----batch_36522ad7-fc75-4b56-8c71-56071383e77b 
Content-Type: application/http 
Content-Transfer-Encoding:binary

GET /contoso.onmicrosoft.com/users/testuser@contoso.onmicrosoft.com?api-version=1.5 HTTP/1.1
Accept: application/json
Host: graph.windows.net

--batch_36522ad7-fc75-4b56-8c71-56071383e77b--

Sintaxis de la respuesta por lotes

La respuesta devuelve un código de estado general para la solicitud por lotes, así como códigos de estado individuales y fragmentos de resultados para cada elemento del lote. La respuesta es un mensaje MIME de varias partes que incluye límites de lote y límites de conjunto de cambios.

Suponiendo que la solicitud por lotes fuera autenticada y recibida correctamente por Graph API, dicha solicitud devuelve el código de estado 202 - Aceptado, incluso si se produce un error en una de las operaciones del lote. Si la propia solicitud por lotes produce un error, lo hará antes de que se ejecute ninguna operación del lote. Por ejemplo, la solicitud por lotes puede producir un error de autenticación, en cuyo caso el código de estado indicará ese error.

El fragmento de respuesta para un elemento de la consulta contiene un código de estado único que indica el éxito o el error de la operación, así como cualquier cuerpo de respuesta adecuado.

Las operaciones dentro de un conjunto de cambios se procesan de forma automática; es decir, o todas las operaciones del conjunto de cambios se realizan correctamente o el conjunto de cambios completo produce un error. Graph API continúa procesando operaciones del conjunto de cambios hasta que se produzca un error en una de ellas. En ese caso, todas las operaciones anteriores del conjunto de cambios se revierten.

Si todas las operaciones de un conjunto de cambios están correctamente procesadas, el código de estado (y el cuerpo de respuesta) para cada operación del conjunto de cambios aparece dentro de la respuesta de dicho conjunto. Si se produce un error en una operación de un conjunto de cambios, solo se devuelve un código de estado único para el conjunto de cambios. Este será el código de estado (y el cuerpo de respuesta) devuelto por la operación con error; por ejemplo, 400 - Solicitud incorrecta o 404 - No encontrado.

Respuesta de ejemplo

En el ejemplo siguiente se muestra la respuesta para la operación por lotes enviada en la solicitud de ejemplo mostrada anteriormente. El estado de la solicitud por lotes está establecido en 202 - Aceptado. Esto indica que no existe ningún problema con la solicitud por lotes en sí. La respuesta a cada elemento del lote se delimita con el identificador de límite batchresponse y cada respuesta a una operación del conjunto de cambios se delimita con un identificador de límite changesetresponse.

A continuación se enumeran los fragmentos de respuesta para cada elemento del lote:

  1. El estado de la solicitud POST para crear el nuevo usuario se establece en 204 - No hay contenido. Esto es porque el encabezado Prefer estaba establecido en return-no-content en la solicitud. Indica que el usuario se creó correctamente.
  2. La respuesta para el segundo elemento del lote contiene dos respuestas 204 - No hay contenido: una para la actualización del objeto de usuario (PATCH) y otra para establecer el vínculo de administrador (PUT) en el conjunto de cambios. Esto indica que ambas operaciones eran correctas.
  3. La respuesta para la solicitud de leer el administrador del usuario devuelve el vínculo al administrador y un estado de 200 - Aceptar.
  4. El estado para el intento de eliminar el usuario es 204 No Content. Esto indica que la operación se realizó correctamente.
  5. El estado para el intento de leer el usuario eliminado es 404 - No encontrado y la respuesta contiene un código y un mensaje que indica que no se encontró el usuario (recurso).
HTTP/1.1 202 Accepted
Cache-Control: no-cache
Pragma: no-cache
Content-Type: multipart/mixed; boundary=batchresponse_1eb70252-25d2-466c-9a1d-7a3f45378b06
Expires: -1
Server: Microsoft-IIS/8.5
ocp-aad-diagnostics-server-name: Nv0YIi2YUldDWu0YPQAXsYwXQ4ttyr7ded6Waf8xyCc=
request-id: 2f7d2f81-3441-4c2a-b494-25cd1d6ce624
client-request-id: f40c00af-3e1f-4198-9261-386f0e3aecc6
x-ms-gateway-rewrite: false
x-ms-dirapi-data-contract-version: 1.5
ocp-aad-session-key: cdhenl3mgHuI3vaRRIQ14uXdwRLUqirNpDXjJP42EzUEvqhhn2NFr22ulR4PsqrM1UD_eSUDItt7J9kUQhNvTT_48q90coHHt2RutCIgPNg.lD81Z0iS2SaHbqkfAaDvbbigoX7ak7rfiUGFby0LOIE
X-Content-Type-Options: nosniff
DataServiceVersion: 1.0;
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
X-Powered-By: ASP.NET
Date: Tue, 20 Jan 2015 23:21:15 GMT
Content-Length: 3065

--batchresponse_1eb70252-25d2-466c-9a1d-7a3f45378b06
Content-Type: multipart/mixed; boundary=changesetresponse_8a63ce5e-ed31-4de6-bc90-9d3ff31debbb--changesetresponse_8a63ce5e-ed31-4de6-bc90-9d3ff31debbb
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 204 No Content
X-Content-Type-Options: nosniff
Cache-Control: no-cache
Preference-Applied: return-no-content
DataServiceVersion: 3.0;
Location: https://graph.windows.net/contoso.onmicrosoft.com/directoryObjects/6a287a96-ede9-44d2-b685-d6fc03a124c5/Microsoft.DirectoryServices.User
DataServiceId: https://graph.windows.net/contoso.onmicrosoft.com/directoryObjects/6a287a96-ede9-44d2-b685-d6fc03a124c5


--changesetresponse_8a63ce5e-ed31-4de6-bc90-9d3ff31debbb----batchresponse_1eb70252-25d2-466c-9a1d-7a3f45378b06
Content-Type: multipart/mixed; boundary=changesetresponse_11ba5cf0-9fba-4995-9f15-bd5c9981cdd6--changesetresponse_11ba5cf0-9fba-4995-9f15-bd5c9981cdd6
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 204 No Content
X-Content-Type-Options: nosniff
Cache-Control: no-cache
DataServiceVersion: 1.0;


--changesetresponse_11ba5cf0-9fba-4995-9f15-bd5c9981cdd6
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 204 No Content
X-Content-Type-Options: nosniff
Cache-Control: no-cache
DataServiceVersion: 1.0;


--changesetresponse_11ba5cf0-9fba-4995-9f15-bd5c9981cdd6----batchresponse_1eb70252-25d2-466c-9a1d-7a3f45378b06
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 200 OK
DataServiceVersion: 3.0;
Content-Type: application/json;odata=minimalmetadata;streaming=true;charset=utf-8
X-Content-Type-Options: nosniff
Cache-Control: no-cache

{
  "odata.metadata":"https://graph.windows.net/contoso.onmicrosoft.com/$metadata#directoryObjects/$links/manager",
  "url":"https://graph.windows.net/contoso.onmicrosoft.com/directoryObjects/a71e4d1c-ce99-40dc-8d4b-390eac63e039/Microsoft.DirectoryServices.User"
}
--batchresponse_1eb70252-25d2-466c-9a1d-7a3f45378b06
Content-Type: multipart/mixed; boundary=changesetresponse_bb215a84-f91e-4486-a771-ba2cc5d429d1--changesetresponse_bb215a84-f91e-4486-a771-ba2cc5d429d1
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 204 No Content
X-Content-Type-Options: nosniff
Cache-Control: no-cache
DataServiceVersion: 1.0;


--changesetresponse_bb215a84-f91e-4486-a771-ba2cc5d429d1----batchresponse_1eb70252-25d2-466c-9a1d-7a3f45378b06
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 404 Not Found
X-Content-Type-Options: nosniff
Cache-Control: no-cache
DataServiceVersion: 3.0;
Content-Type: application/json;odata=minimalmetadata;streaming=true;charset=utf-8

{
  "odata.error":
    {
      "code":"Request_ResourceNotFound",
      "message":
        {
          "lang":"en",
          "value":"Resource 'testuser@contoso.onmicrosoft.com' does not exist or one of its queried reference-property objects are not present."
        }
    }
}
--batchresponse_1eb70252-25d2-466c-9a1d-7a3f45378b06--

Respuesta de error de ejemplo

Según se explicó anteriormente, Graph API devuelve un código de error 202 - Aceptado para todo el lote si puede aceptar el lote; es decir, si la solicitud por lotes tiene el formato correcto y no existen errores como, por ejemplo, un error de autenticación. De lo contrario, Graph API devuelve el error correspondiente y no procesa el lote. Si se produce un error en un elemento individual dentro del lote, el fragmento de respuesta para ese elemento contendrá un código de estado y un cuerpo de respuesta que indica el error. Cuando se produce un error en una operación dentro de un conjunto de cambios, se devolverá un fragmento de respuesta única para todo el conjunto de cambios y ese fragmento contendrá el estado de código y el cuerpo de respuesta asociados a la operación en la que se produjo el error.

En el ejemplo siguiente se muestra una respuesta de la solicitud por lotes que contiene un conjunto de cambios en el que se produjo un error en una de las operaciones. Tenga en cuenta que la respuesta por lotes devuelve el código de estado 202 - Aceptado. El código de estado devuelto para el conjunto de cambios indica que se produjo un error en una operación con un estado 404 - No encontrado. Se incluye información adicional sobre el error en el cuerpo de respuesta para la operación en la que se produjo el error. El elemento code especifica el código de error de Graph API y el elemento message contiene la cadena del mensaje de error. En este ejemplo, se ha aplicado una sangría al cuerpo de respuesta para facilitar la lectura.

HTTP/1.1 202 Accepted
Cache-Control: no-cache
Pragma: no-cache
Content-Type: multipart/mixed; boundary=batchresponse_3ac28387-a100-4758-8998-8b9ec36f9fdc
Expires: -1
Server: Microsoft-IIS/8.5
ocp-aad-diagnostics-server-name: 1l3fvSoDCV+VKoBCuHRN+HIwCACBOck3dqmtCGj+aiU=
request-id: e434261b-c32f-48b4-b21d-3e1beab6d525
client-request-id: 236bf26e-b4e8-40a4-b6fb-d41105a7b178
x-ms-gateway-rewrite: false
x-ms-dirapi-data-contract-version: 1.5
ocp-aad-session-key: 9aOaAUxX95OZ0ctrYbeLUproN-37GypZXrss0PYKhEfqamKRG-C68hFcCw5h-ZCWFqBrXPrldGEnjq4CKKr0bW91tjrdo-BlwAqHxbP5jq4.FaXtVZni3cSsWFRMSjQAbjiluPcEvZofwp9OH3t1fyk
X-Content-Type-Options: nosniff
DataServiceVersion: 1.0;
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
X-Powered-By: ASP.NET
Date: Wed, 21 Jan 2015 21:13:25 GMT
Content-Length: 779

--batchresponse_3ac28387-a100-4758-8998-8b9ec36f9fdc
Content-Type: multipart/mixed; boundary=changesetresponse_72ba9a5a-2da3-4d39-ae4f-dd9527efd742--changesetresponse_72ba9a5a-2da3-4d39-ae4f-dd9527efd742
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 404 Not Found
X-Content-Type-Options: nosniff
DataServiceVersion: 3.0;
Content-Type: application/json;odata=minimalmetadata;streaming=true;charset=utf-8

{
  "odata.error":
    {
      "code":"Request_ResourceNotFound",
      "message":
        {
          "lang":"en",
          "value":"Resource 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee' does not exist or one of its queried reference-property objects are not present."
        }
    }
}
--changesetresponse_72ba9a5a-2da3-4d39-ae4f-dd9527efd742----batchresponse_3ac28387-a100-4758-8998-8b9ec36f9fdc--

Como referencia, en el ejemplo siguiente se muestra el lote que generó la respuesta anterior. Contiene un único conjunto de cambios que agrega tres usuarios a un grupo. Los identificadores de objeto para los dos últimos usuarios son ficticios: eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee y ffffffff-ffff-ffff-ffff-ffffffffffff. La URL del lote y los encabezados de solicitud asociados se omiten para mayor brevedad.

--batch_36522ad7-fc75-4b56-8c71-56071383e77b 
Content-Type: multipart/mixed; boundary=changeset_5a769eb2-d1a7-4a10-94f6-d1a5ed5c4bc0 
Content-Length: 1432

--changeset_5a769eb2-d1a7-4a10-94f6-d1a5ed5c4bc0 
Content-Type: application/http 
Content-Transfer-Encoding: binary 

POST /contoso.onmicrosoft.com/groups/fc15e7ef-993f-4865-bf37-317d9b8017b8/$links/members?api-version=1.5 HTTP/1.1
Content-Type: application/json
Accept: application/json
Content-Length: 112
Host: graph.windows.net

{
  "url":"https://graph.windows.net/contoso.onmicrosoft.com/users/a71e4d1c-ce99-40dc-8d4b-390eac63e039"
}

--changeset_5a769eb2-d1a7-4a10-94f6-d1a5ed5c4bc0 
Content-Type: application/http 
Content-Transfer-Encoding: binary 

POST /contoso.onmicrosoft.com/groups/fc15e7ef-993f-4865-bf37-317d9b8017b8/$links/members?api-version=1.5 HTTP/1.1
Content-Type: application/json
Accept: application/json
Content-Length: 112
Host: graph.windows.net

{
  "url":"https://graph.windows.net/contoso.onmicrosoft.com/users/eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee
"
}

--changeset_5a769eb2-d1a7-4a10-94f6-d1a5ed5c4bc0 
Content-Type: application/http 
Content-Transfer-Encoding: binary 

POST /contoso.onmicrosoft.com/groups/fc15e7ef-993f-4865-bf37-317d9b8017b8/$links/members?api-version=1.5 HTTP/1.1
Content-Type: application/json
Accept: application/json
Content-Length: 112
Host: graph.windows.net

{
  "url":"https://graph.windows.net/contoso.onmicrosoft.com/users/ffffffff-ffff-ffff-ffff-ffffffffffff"
}

--changeset_5a769eb2-d1a7-4a10-94f6-d1a5ed5c4bc0----batch_36522ad7-fc75-4b56-8c71-56071383e77b--

Recursos adicionales