Importación y exportación de identidades de dispositivo de IoT Hub de forma masivaImport and export IoT Hub device identities in bulk

Cada Centro de IoT tiene un registro de identidad que se puede usar para crear recursos por dispositivo en el servicio.Each IoT hub has an identity registry you can use to create per-device resources in the service. El registro de identidad también permite controlar el acceso a los puntos de conexión accesibles desde los dispositivos.The identity registry also enables you to control access to the device-facing endpoints. En este artículo se describe cómo importar y exportar identidades de dispositivo de forma masiva hacia y desde un Registro de identidad.This article describes how to import and export device identities in bulk to and from an identity registry. Para ver un ejemplo en funcionamiento en C# y obtener información sobre cómo puede usar esta funcionalidad a la hora de clonar un centro en otra región, consulte Cómo clonar una instancia de IoT Hub.To see a working sample in C# and learn how you can use this capability when cloning a hub to a different region, see How to Clone an IoT Hub.

Nota

Las características descritas en este artículo solo están disponibles en el nivel estándar de IoT Hub.The features described in this article are available only in the standard tier of IoT Hub. Para más información sobre los niveles Básico y Estándar de IoT Hub, consulte el artículo sobre cómo elegir el nivel de IoT Hub correcto.For more information about the basic and standard IoT Hub tiers, see Choose the right IoT Hub tier.

Las operaciones de importación y exportación tienen lugar en el contexto de Trabajos que permiten ejecutar operaciones de servicio de forma masiva en un IoT Hub.Import and export operations take place in the context of Jobs that enable you to execute bulk service operations against an IoT hub.

La clase RegistryManager incluye los métodos ExportDevicesAsync y ImportDevicesAsync, que usan el marco Trabajo.The RegistryManager class includes the ExportDevicesAsync and ImportDevicesAsync methods that use the Job framework. Estos métodos le permiten exportar, importar y sincronizar la totalidad de un Registro de identidad de IoT Hub.These methods enable you to export, import, and synchronize the entirety of an IoT hub identity registry.

En este tema se describe el uso de la clase RegistryManager y del sistema de trabajo para realizar importaciones y exportaciones en bloque de dispositivos a y desde un registro de identidad de un centro de IoT.This topic discusses using the RegistryManager class and Job system to perform bulk imports and exports of devices to and from an IoT hub’s identity registry. También puede usar el servicio Azure IoT Hub Device Provisioning para habilitar el aprovisionamiento Just-In-Time sin intervención del usuario de uno o varios centros de IoT sin necesidad de ninguna intervención humana.You can also use the Azure IoT Hub Device Provisioning Service to enable zero-touch, just-in-time provisioning to one or more IoT hubs without requiring human intervention. Para más información, consulte la documentación del servicio de aprovisionamiento.To learn more, see the provisioning service documentation.

¿Qué son los trabajos?What are jobs?

Las operaciones de Registro de identidad usan el sistema de trabajo cuando la operación:Identity registry operations use the Job system when the operation:

  • Tiene un tiempo de ejecución potencialmente largo en comparación con las operaciones en tiempo de ejecución estándar.Has a potentially long execution time compared to standard run-time operations.

  • Devuelve una gran cantidad de datos al usuario.Returns a large amount of data to the user.

En estos casos, en lugar de una única API en espera o que bloquea el resultado de la operación, esta crea de forma asincrónica un Trabajo para ese Centro de IoT.Instead of a single API call waiting or blocking on the result of the operation, the operation asynchronously creates a Job for that IoT hub. La operación después devuelve inmediatamente un objeto JobProperties.The operation then immediately returns a JobProperties object.

El siguiente fragmento de código de C# muestra cómo crear un trabajo de exportación:The following C# code snippet shows how to create an export job:

// Call an export job on the IoT Hub to retrieve all devices
JobProperties exportJob = await 
  registryManager.ExportDevicesAsync(containerSasUri, false);

Nota

Para usar la clase RegistryManager en el código de C#, agregue el paquete de NuGet Microsoft.Azure.Devices al proyecto.To use the RegistryManager class in your C# code, add the Microsoft.Azure.Devices NuGet package to your project. La clase RegistryManager está en el espacio de nombres Microsoft.Azure.Devices.The RegistryManager class is in the Microsoft.Azure.Devices namespace.

Puede usar la clase RegistryManager para consultar el estado de Trabajo con los metadatos de JobProperties devueltos.You can use the RegistryManager class to query the state of the Job using the returned JobProperties metadata. Para crear una instancia de la clase RegistryManager, use el método CreateFromConnectionString.To create an instance of the RegistryManager class, use the CreateFromConnectionString method.

RegistryManager registryManager =
  RegistryManager.CreateFromConnectionString("{your IoT Hub connection string}");

Para buscar la cadena de conexión de su IoT Hub en Azure Portal:To find the connection string for your IoT hub, in the Azure portal:

  • Vaya a su instancia de IoT Hub.Navigate to your IoT hub.

  • Seleccione Directivas de acceso compartido.Select Shared access policies.

  • Seleccione una directiva teniendo en cuenta los permisos que necesita.Select a policy, taking into account the permissions you need.

  • Copie la cadena de conexión desde el panel del lado derecho de la pantalla.Copy the connectionstring from the panel on the right-hand side of the screen.

El siguiente fragmento de código de C# muestra cómo sondear cada cinco segundos para ver si el trabajo ha terminado de ejecutarse:The following C# code snippet shows how to poll every five seconds to see if the job has finished executing:

// Wait until job is finished
while(true)
{
  exportJob = await registryManager.GetJobAsync(exportJob.JobId);
  if (exportJob.Status == JobStatus.Completed || 
      exportJob.Status == JobStatus.Failed ||
      exportJob.Status == JobStatus.Cancelled)
  {
    // Job has finished executing
    break;
  }

  await Task.Delay(TimeSpan.FromSeconds(5));
}

Límites de trabajo de importación y exportación de dispositivosDevice import/export job limits

Solo se permite un trabajo activo de importación o exportación de dispositivos de forma simultánea para todos los niveles de IoT Hub.Only 1 active device import or export job is allowed at a time for all IoT Hub tiers. IoT Hub también tiene límites de velocidad para las operaciones de trabajos.IoT Hub also has limits for rate of jobs operations. Para más información, vea Referencia: Cuotas y limitación de IoT Hub.To learn more, see Reference - IoT Hub quotas and throttling.

Exportación de dispositivosExport devices

Use el método ExportDevicesAsync para exportar la totalidad de un Registro de identidad de IoT Hub a un contenedor de blobs de Azure Storage mediante una firma de acceso compartido.Use the ExportDevicesAsync method to export the entirety of an IoT hub identity registry to an Azure Storage blob container using a Shared Access Signature.

Este método le permite crear copias de seguridad confiables de la información del dispositivo en un contenedor de blobs que usted controle.This method enables you to create reliable backups of your device information in a blob container that you control.

El método ExportDevicesAsync requiere dos parámetros:The ExportDevicesAsync method requires two parameters:

  • Una cadena que contiene un identificador URI de un contenedor de blobs.A string that contains a URI of a blob container. Este identificador URI debe contener un token SAS que conceda acceso de escritura al contenedor.This URI must contain a SAS token that grants write access to the container. El trabajo crea un blob en bloques en este contenedor para almacenar los datos serializados de exportación del dispositivo.The job creates a block blob in this container to store the serialized export device data. El token de SAS debe incluir estos permisos:The SAS token must include these permissions:

    SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.Read 
       | SharedAccessBlobPermissions.Delete
    
  • Un valor booleano que indica si desea excluir las claves de autenticación de los datos de exportación.A boolean that indicates if you want to exclude authentication keys from your export data. Si es false, las claves de autenticación se incluyen en la exportación.If false, authentication keys are included in export output. De lo contrario, las claves se exportan como null.Otherwise, keys are exported as null.

El siguiente fragmento de código de C# muestra cómo iniciar un trabajo de exportación que incluye las claves de autenticación de dispositivo en los datos de exportación y luego sondea la finalización:The following C# code snippet shows how to initiate an export job that includes device authentication keys in the export data and then poll for completion:

// Call an export job on the IoT Hub to retrieve all devices
JobProperties exportJob = 
  await registryManager.ExportDevicesAsync(containerSasUri, false);

// Wait until job is finished
while(true)
{
    exportJob = await registryManager.GetJobAsync(exportJob.JobId);
    if (exportJob.Status == JobStatus.Completed || 
        exportJob.Status == JobStatus.Failed ||
        exportJob.Status == JobStatus.Cancelled)
    {
    // Job has finished executing
    break;
    }

    await Task.Delay(TimeSpan.FromSeconds(5));
}

El trabajo almacena su salida en el contenedor de blobs proporcionado como un blob en bloques con el nombre devices.txt.The job stores its output in the provided blob container as a block blob with the name devices.txt. Los datos de salida se componen de datos de dispositivos serializados de JSON, con un dispositivo por línea.The output data consists of JSON serialized device data, with one device per line.

En el siguiente ejemplo se muestran los datos de salida:The following example shows the output data:

{"id":"Device1","eTag":"MA==","status":"enabled","authentication":{"symmetricKey":{"primaryKey":"abc=","secondaryKey":"def="}}}
{"id":"Device2","eTag":"MA==","status":"enabled","authentication":{"symmetricKey":{"primaryKey":"abc=","secondaryKey":"def="}}}
{"id":"Device3","eTag":"MA==","status":"disabled","authentication":{"symmetricKey":{"primaryKey":"abc=","secondaryKey":"def="}}}
{"id":"Device4","eTag":"MA==","status":"disabled","authentication":{"symmetricKey":{"primaryKey":"abc=","secondaryKey":"def="}}}
{"id":"Device5","eTag":"MA==","status":"enabled","authentication":{"symmetricKey":{"primaryKey":"abc=","secondaryKey":"def="}}}

Si un dispositivo tiene datos gemelos, estos también se exportan junto con los datos del dispositivo. En el siguiente ejemplo se muestra este formato. Todos los datos de la línea "twinETag" hasta el final son datos gemelos.All data from the "twinETag" line until the end is twin data.

{
   "id":"export-6d84f075-0",
   "eTag":"MQ==",
   "status":"enabled",
   "statusReason":"firstUpdate",
   "authentication":null,
   "twinETag":"AAAAAAAAAAI=",
   "tags":{
      "Location":"LivingRoom"
   },
   "properties":{
      "desired":{
         "Thermostat":{
            "Temperature":75.1,
            "Unit":"F"
         },
         "$metadata":{
            "$lastUpdated":"2017-03-09T18:30:52.3167248Z",
            "$lastUpdatedVersion":2,
            "Thermostat":{
               "$lastUpdated":"2017-03-09T18:30:52.3167248Z",
               "$lastUpdatedVersion":2,
               "Temperature":{
                  "$lastUpdated":"2017-03-09T18:30:52.3167248Z",
                  "$lastUpdatedVersion":2
               },
               "Unit":{
                  "$lastUpdated":"2017-03-09T18:30:52.3167248Z",
                  "$lastUpdatedVersion":2
               }
            }
         },
         "$version":2
      },
      "reported":{
         "$metadata":{
            "$lastUpdated":"2017-03-09T18:30:51.1309437Z"
         },
         "$version":1
      }
   }
}

Si necesita acceso a los datos en el código, puede deserializar fácilmente estos datos mediante la clase ExportImportDevice .If you need access to this data in code, you can easily deserialize this data using the ExportImportDevice class. El siguiente fragmento de código de C# muestra cómo leer la información de dispositivo que se ha exportado previamente a un blob en bloques:The following C# code snippet shows how to read device information that was previously exported to a block blob:

var exportedDevices = new List<ExportImportDevice>();

using (var streamReader = new StreamReader(await blob.OpenReadAsync(AccessCondition.GenerateIfExistsCondition(), null, null), Encoding.UTF8))
{
  while (streamReader.Peek() != -1)
  {
    string line = await streamReader.ReadLineAsync();
    var device = JsonConvert.DeserializeObject<ExportImportDevice>(line);
    exportedDevices.Add(device);
  }
}

Importación de dispositivosImport devices

El método ImportDevicesAsync de la clase RegistryManager le permite realizar operaciones de sincronización e importación masiva en un Registro de identidad de IoT Hub.The ImportDevicesAsync method in the RegistryManager class enables you to perform bulk import and synchronization operations in an IoT hub identity registry. Al igual que el método ExportDevicesAsync, el método ImportDevicesAsync usa el marco Trabajo.Like the ExportDevicesAsync method, the ImportDevicesAsync method uses the Job framework.

Tenga cuidado con el método ImportDevicesAsync porque además del aprovisionamiento de nuevos dispositivos en el Registro de identidad, también puede actualizar y eliminar dispositivos existentes.Take care using the ImportDevicesAsync method because in addition to provisioning new devices in your identity registry, it can also update and delete existing devices.

Advertencia

Una operación de importación no se puede deshacer.An import operation cannot be undone. Realice siempre una copia de seguridad de los datos existentes mediante el método ExportDevicesAsync en otro contenedor de blobs antes de realizar cambios masivos en el Registro de identidad.Always back up your existing data using the ExportDevicesAsync method to another blob container before you make bulk changes to your identity registry.

El método ImportDevicesAsync requiere dos parámetros:The ImportDevicesAsync method takes two parameters:

  • Una cadena que contiene un identificador URI de un contenedor de blobs de Azure Storage para usar como entrada para el trabajo.A string that contains a URI of an Azure Storage blob container to use as input to the job. Este identificador URI debe contener un token SAS que conceda acceso de lectura al contenedor.This URI must contain a SAS token that grants read access to the container. Este contenedor debe incluir un blob con el nombre devices.txt que contenga los datos de dispositivo serializados para importar en el Registro de identidad.This container must contain a blob with the name devices.txt that contains the serialized device data to import into your identity registry. Los datos de importación deben contener la información del dispositivo en el mismo formato JSON que usa el trabajo ExportImportDevice cuando crea un blob devices.txt.The import data must contain device information in the same JSON format that the ExportImportDevice job uses when it creates a devices.txt blob. El token de SAS debe incluir estos permisos:The SAS token must include these permissions:

    SharedAccessBlobPermissions.Read
    
  • Una cadena que contenga un identificador URI de un contenedor de blobs de Azure Storage para usar como salida del trabajo.A string that contains a URI of an Azure Storage blob container to use as output from the job. El trabajo crea un blob en bloques en este contenedor para almacenar cualquier información de error del Trabajode importación finalizado.The job creates a block blob in this container to store any error information from the completed import Job. El token de SAS debe incluir estos permisos:The SAS token must include these permissions:

    SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.Read 
       | SharedAccessBlobPermissions.Delete
    

Nota

Los dos parámetros pueden apuntar al mismo contenedor de blobs.The two parameters can point to the same blob container. Los parámetros independientes simplemente habilitan más control sobre sus datos, ya que el contenedor de salida requiere permisos adicionales.The separate parameters simply enable more control over your data as the output container requires additional permissions.

El siguiente fragmento de código de C# muestra cómo iniciar un trabajo de importación:The following C# code snippet shows how to initiate an import job:

JobProperties importJob = 
   await registryManager.ImportDevicesAsync(containerSasUri, containerSasUri);

Este método también se puede usar para importar los datos para el dispositivo gemelo.This method can also be used to import the data for the device twin. El formato de la entrada de datos es el mismo que se muestra en la sección ExportDevicesAsync.The format for the data input is the same as the format shown in the ExportDevicesAsync section. De esta manera, se pueden volver a importar los datos exportados.In this way, you can reimport the exported data. El valor de $metadata es opcional.The $metadata is optional.

Comportamiento de la importaciónImport behavior

Puede usar el método ImportDevicesAsync para realizar las siguientes operaciones de forma masiva en el Registro de identidad:You can use the ImportDevicesAsync method to perform the following bulk operations in your identity registry:

  • Registro masivo de nuevos dispositivosBulk registration of new devices
  • Eliminación masiva de dispositivos existentesBulk deletions of existing devices
  • Cambios masivos de estado (habilitar o deshabilitar dispositivos)Bulk status changes (enable or disable devices)
  • Asignación masiva de nuevas claves de autenticación de dispositivosBulk assignment of new device authentication keys
  • Regeneración automática masiva de claves de autenticación de dispositivosBulk auto-regeneration of device authentication keys
  • Actualización masiva de datos gemelosBulk update of twin data

Puede realizar cualquier combinación de las operaciones precedentes en una única llamada ImportDevicesAsync.You can perform any combination of the preceding operations within a single ImportDevicesAsync call. Por ejemplo, puede registrar nuevos dispositivos y eliminar o actualizar los dispositivos existentes al mismo tiempo.For example, you can register new devices and delete or update existing devices at the same time. Cuando se utiliza junto con el método ExportDevicesAsync , puede migrar completamente todos los dispositivos de un Centro de IoT a otro.When used along with the ExportDevicesAsync method, you can completely migrate all your devices from one IoT hub to another.

Si el archivo de importación especifica metadatos gemelos, estos sobrescriben los existentes.If the import file includes twin metadata, then this metadata overwrites the existing twin metadata. Si el archivo de importación no incluye metadatos gemelos, solo se actualizan los metadatos de lastUpdateTime que usan la hora actual.If the import file does not include twin metadata, then only the lastUpdateTime metadata is updated using the current time.

Use la propiedad opcional importMode en los datos de serialización de importación para cada dispositivo para controlar el proceso de importación por dispositivo.Use the optional importMode property in the import serialization data for each device to control the import process per-device. La propiedad importMode tiene las siguientes opciones:The importMode property has the following options:

importModeimportMode DESCRIPCIÓNDescription
createOrUpdatecreateOrUpdate Si no existe un dispositivo con el valor ID especificado, se registra por primera vez.If a device does not exist with the specified ID, it is newly registered.
Si el dispositivo ya existe, la información existente se sobrescribe con los datos de entrada proporcionados con independencia del valor ETag .If the device already exists, existing information is overwritten with the provided input data without regard to the ETag value.
El usuario puede especificar opcionalmente datos gemelos junto con los datos del dispositivo.The user can optionally specify twin data along with the device data. El valor etag del gemelo, si se especifica, se procesa por separado del etag del dispositivo.The twin’s etag, if specified, is processed independently from the device’s etag. Si no coincide con el etag del gemelo existente, se escribe un error en el archivo de registro.If there is a mismatch with the existing twin’s etag, an error is written to the log file.
crearcreate Si no existe un dispositivo con el valor ID especificado, se registra por primera vez.If a device does not exist with the specified ID, it is newly registered.
Si el dispositivo ya existe, se escribe un error en el archivo de registro.If the device already exists, an error is written to the log file.
El usuario puede especificar opcionalmente datos gemelos junto con los datos del dispositivo.The user can optionally specify twin data along with the device data. El valor etag del gemelo, si se especifica, se procesa por separado del etag del dispositivo.The twin’s etag, if specified, is processed independently from the device’s etag. Si no coincide con el etag del gemelo existente, se escribe un error en el archivo de registro.If there is a mismatch with the existing twin’s etag, an error is written to the log file.
updateupdate Si ya existe un dispositivo con el identificador especificado, la información existente se sobrescribe con los datos de entrada proporcionados con independencia del valor ETag.If a device already exists with the specified ID, existing information is overwritten with the provided input data without regard to the ETag value.
Si el dispositivo no existe, se escribe un error en el archivo de registro.If the device does not exist, an error is written to the log file.
updateIfMatchETagupdateIfMatchETag Si ya existe un dispositivo con el identificador especificado, la información existente se sobrescribe con los datos de entrada proporcionados solo si hay un valor ETag que coincida.If a device already exists with the specified ID, existing information is overwritten with the provided input data only if there is an ETag match.
Si el dispositivo no existe, se escribe un error en el archivo de registro.If the device does not exist, an error is written to the log file.
Si no existe la coincidencia con ETag , se escribe un error en el archivo de registro.If there is an ETag mismatch, an error is written to the log file.
createOrUpdateIfMatchETagcreateOrUpdateIfMatchETag Si no existe un dispositivo con el valor ID especificado, se registra por primera vez.If a device does not exist with the specified ID, it is newly registered.
Si el dispositivo ya existe, la información existente se sobrescribe con los datos de entrada proporcionados solo si hay una coincidencia con ETag .If the device already exists, existing information is overwritten with the provided input data only if there is an ETag match.
Si no existe la coincidencia con ETag , se escribe un error en el archivo de registro.If there is an ETag mismatch, an error is written to the log file.
El usuario puede especificar opcionalmente datos gemelos junto con los datos del dispositivo.The user can optionally specify twin data along with the device data. El valor etag del gemelo, si se especifica, se procesa por separado del etag del dispositivo.The twin’s etag, if specified, is processed independently from the device’s etag. Si no coincide con el etag del gemelo existente, se escribe un error en el archivo de registro.If there is a mismatch with the existing twin’s etag, an error is written to the log file.
deletedelete Si ya existe un dispositivo con el identificador especificado, se eliminará con independencia del valor ETag.If a device already exists with the specified ID, it is deleted without regard to the ETag value.
Si el dispositivo no existe, se escribe un error en el archivo de registro.If the device does not exist, an error is written to the log file.
deleteIfMatchETagdeleteIfMatchETag Si ya existe un dispositivo con el identificador especificado, solo se eliminará si hay una coincidencia con ETag.If a device already exists with the specified ID, it is deleted only if there is an ETag match. Si el dispositivo no existe, se escribe un error en el archivo de registro.If the device does not exist, an error is written to the log file.
Si no existe una coincidencia con ETag, se escribe un error en el archivo de registro.If there is an ETag mismatch, an error is written to the log file.

Nota

Si los datos de serialización no definen explícitamente una marca importMode para un dispositivo, se establece de manera predeterminada en createOrUpdate durante la operación de importación.If the serialization data does not explicitly define an importMode flag for a device, it defaults to createOrUpdate during the import operation.

Ejemplo de importación de dispositivos: aprovisionamiento masivo de dispositivosImport devices example – bulk device provisioning

El siguiente ejemplo de código de C# muestra cómo generar varias identidades de dispositivo que:The following C# code sample illustrates how to generate multiple device identities that:

  • Incluyen claves de autenticación.Include authentication keys.
  • Escriben la información del dispositivo en un blob en bloques.Write that device information to a block blob.
  • Importan los dispositivos en el Registro de identidad.Import the devices into the identity registry.
// Provision 1,000 more devices
var serializedDevices = new List<string>();

for (var i = 0; i < 1000; i++)
{
  // Create a new ExportImportDevice
  // CryptoKeyGenerator is in the Microsoft.Azure.Devices.Common namespace
  var deviceToAdd = new ExportImportDevice()
  {
    Id = Guid.NewGuid().ToString(),
    Status = DeviceStatus.Enabled,
    Authentication = new AuthenticationMechanism()
    {
      SymmetricKey = new SymmetricKey()
      {
        PrimaryKey = CryptoKeyGenerator.GenerateKey(32),
        SecondaryKey = CryptoKeyGenerator.GenerateKey(32)
      }
    },
    ImportMode = ImportMode.Create
  };

  // Add device to the list
  serializedDevices.Add(JsonConvert.SerializeObject(deviceToAdd));
}

// Write the list to the blob
var sb = new StringBuilder();
serializedDevices.ForEach(serializedDevice => sb.AppendLine(serializedDevice));
await blob.DeleteIfExistsAsync();

using (CloudBlobStream stream = await blob.OpenWriteAsync())
{
  byte[] bytes = Encoding.UTF8.GetBytes(sb.ToString());
  for (var i = 0; i < bytes.Length; i += 500)
  {
    int length = Math.Min(bytes.Length - i, 500);
    await stream.WriteAsync(bytes, i, length);
  }
}

// Call import using the blob to add new devices
// Log information related to the job is written to the same container
// This normally takes 1 minute per 100 devices
JobProperties importJob =
   await registryManager.ImportDevicesAsync(containerSasUri, containerSasUri);

// Wait until job is finished
while(true)
{
  importJob = await registryManager.GetJobAsync(importJob.JobId);
  if (importJob.Status == JobStatus.Completed || 
      importJob.Status == JobStatus.Failed ||
      importJob.Status == JobStatus.Cancelled)
  {
    // Job has finished executing
    break;
  }

  await Task.Delay(TimeSpan.FromSeconds(5));
}

Ejemplo de importación de dispositivos: eliminación masivaImport devices example – bulk deletion

El ejemplo de código siguiente muestra cómo eliminar los dispositivos que ha agregado con el ejemplo de código anterior:The following code sample shows you how to delete the devices you added using the previous code sample:

// Step 1: Update each device's ImportMode to be Delete
sb = new StringBuilder();
serializedDevices.ForEach(serializedDevice =>
{
  // Deserialize back to an ExportImportDevice
  var device = JsonConvert.DeserializeObject<ExportImportDevice>(serializedDevice);

  // Update property
  device.ImportMode = ImportMode.Delete;

  // Re-serialize
  sb.AppendLine(JsonConvert.SerializeObject(device));
});

// Step 2: Write the new import data back to the block blob
await blob.DeleteIfExistsAsync();
using (CloudBlobStream stream = await blob.OpenWriteAsync())
{
  byte[] bytes = Encoding.UTF8.GetBytes(sb.ToString());
  for (var i = 0; i < bytes.Length; i += 500)
  {
    int length = Math.Min(bytes.Length - i, 500);
    await stream.WriteAsync(bytes, i, length);
  }
}

// Step 3: Call import using the same blob to delete all devices
importJob = await registryManager.ImportDevicesAsync(containerSasUri, containerSasUri);

// Wait until job is finished
while(true)
{
  importJob = await registryManager.GetJobAsync(importJob.JobId);
  if (importJob.Status == JobStatus.Completed || 
      importJob.Status == JobStatus.Failed ||
      importJob.Status == JobStatus.Cancelled)
  {
    // Job has finished executing
    break;
  }

  await Task.Delay(TimeSpan.FromSeconds(5));
}

Obtención del identificador URI de SAS del contenedorGet the container SAS URI

El ejemplo de código siguiente muestra cómo generar un identificador URI de SAS con permisos de lectura, escritura y eliminación para un contenedor de blobs:The following code sample shows you how to generate a SAS URI with read, write, and delete permissions for a blob container:

static string GetContainerSasUri(CloudBlobContainer container)
{
  // Set the expiry time and permissions for the container.
  // In this case no start time is specified, so the
  // shared access signature becomes valid immediately.
  var sasConstraints = new SharedAccessBlobPolicy();
  sasConstraints.SharedAccessExpiryTime = DateTime.UtcNow.AddHours(24);
  sasConstraints.Permissions = 
    SharedAccessBlobPermissions.Write | 
    SharedAccessBlobPermissions.Read | 
    SharedAccessBlobPermissions.Delete;

  // Generate the shared access signature on the container,
  // setting the constraints directly on the signature.
  string sasContainerToken = container.GetSharedAccessSignature(sasConstraints);

  // Return the URI string for the container,
  // including the SAS token.
  return container.Uri + sasContainerToken;
}

Pasos siguientesNext steps

En este artículo, aprendió a realizar operaciones de forma masiva en el Registro de identidad en un centro de IoT.In this article, you learned how to perform bulk operations against the identity registry in an IoT hub. Muchas de estas operaciones, entre las que se incluyen cómo mover dispositivos de un centro a otro, se usan en la sección Administración de dispositivos registrados en la instancia de IoT Hub del artículo Cómo clonar una instancia de IoT Hub.Many of these operations, including how to move devices from one hub to another, are used in the Managing devices registered to the IoT hub section of How to Clone an IoT Hub.

El artículo de clonación tiene un ejemplo práctico asociado, el cual se encuentra en los ejemplos de C# de IoT de esta página: Ejemplos de Azure IoT para C#, en el proyecto ImportExportDevicesSample.The cloning article has a working sample associated with it, which is located in the IoT C# samples on this page: Azure IoT Samples for C#, with the project being ImportExportDevicesSample. Puede descargar el ejemplo y probarlo; encontrará las instrucciones en el artículo Cómo clonar una instancia de IoT Hub.You can download the sample and try it out; there are instructions in the How to Clone an IoT Hub article.

Para obtener más información sobre la administración de Azure IoT Hub, consulte los artículos siguientes:To learn more about managing Azure IoT Hub, check out the following articles:

Para explorar aún más las funcionalidades de IoT Hub, consulte:To further explore the capabilities of IoT Hub, see:

Para explorar el uso del servicio IoT Hub Device Provisioning para habilitar el aprovisionamiento Just-In-Time sin intervención del usuario, vea:To explore using the IoT Hub Device Provisioning Service to enable zero-touch, just-in-time provisioning, see: