Partager via


Gérer les jumeaux numériques

Les entités de votre environnement sont représentées par des jumeaux numériques. La gestion de vos jumeaux numériques peut inclure la création, la modification et la suppression.

Cet article se concentre sur la gestion des jumeaux numériques. Pour utiliser des relations et le graphe des jumeaux dans leur ensemble, consultez Gérer le graphe de jumeaux et les relations.

Conseil

Toutes les fonctions du Kit de développement logiciel (SDK) sont disponibles en versions synchrone et asynchrone.

Prérequis

Pour utiliser Azure Digital Twins dans cet article, vous avez besoin d’une instance Azure Digital Twins et des autorisations requises pour l’utiliser. Si vous disposez déjà d’une instance Azure Digital Twins configurée, vous pouvez utiliser cette instance et passer à la section suivante. Dans le cas contraire, suivez les instructions indiquées dans Configurer une instance et l’authentification. Les instructions contiennent des informations qui vous aideront à vérifier que vous avez correctement effectué chaque étape.

Une fois l’instance configurée, notez son nom d’hôte. Vous trouverez le nom d’hôte dans le portail Azure.

Interfaces développeur

Cet article montre comment effectuer différentes opérations de gestion à l’aide du kit SDK .NET (C#). Vous pouvez également créer les mêmes appels de gestion à l’aide des autres kits de langage SDK décrits dans les API Azure Digital Twins et kits SDK.

Les autres interfaces développeur qui peuvent être utilisées pour effectuer ces opérations sont les suivantes :

Visualisation

Azure Digital Twins Explorer est un outil visuel permettant d’explorer les données dans votre graphique Azure Digital Twins. Vous pouvez utiliser l’explorateur pour afficher, interroger et modifier vos modèles, vos jumeaux et vos relations.

Pour en savoir plus sur l’outil Azure Digital Twins Explorer, consultez Azure Digital Twins Explorer. Pour obtenir des instructions détaillées sur l’utilisation de ses fonctionnalités, consultez Utilisation d’Azure Digital Twins Explorer.

Voici à quoi ressemble la visualisation :

Capture d’écran d’Azure Digital Twins Explorer montrant des exemples de modèles et de jumeaux

Créer un jumeau numérique

Pour créer un jumeau, vous utilisez la méthode CreateOrReplaceDigitalTwinAsync() sur le client de service comme suit :

await client.CreateOrReplaceDigitalTwinAsync<BasicDigitalTwin>(twinId, initData);

Pour créer un jumeau numérique, vous devez fournir les éléments suivants :

  • Une valeur d’identifiant que vous souhaitez attribuer au jumeau numérique (vous définissez cet identifiant lors de la création du jumeau)
  • Le modèle à utiliser
  • Toute initialisation souhaitée des données de jumeau, y compris…
    • Propriétés (initialisation facultative) : si vous le souhaitez, vous pouvez définir les valeurs initiales de propriétés du jumeau numérique. Les propriétés sont considérées comme facultatives et peuvent être définies ultérieurement, mais notez qu’elles ne s’affichent pas dans le cadre d’un jumeau tant qu’elles n’ont pas été définies.
    • Composants (initialisation requise s’ils sont présents sur le jumeau) : si votre jumeau contient des composants, ceux-ci doivent être initialisés lors de la création du jumeau. Il peut s’agir d’objets vides, mais les composants proprement dits doivent exister.

Le modèle et les éventuelles valeurs des propriétés initiales sont fournis par le biais du paramètre initData, qui est une chaîne JSON contenant les données pertinentes. Pour plus d’informations sur la structuration de cet objet, passez à la section suivante.

Conseil

Après la création ou la mise à jour d’un jumeau, il peut y avoir une latence allant jusqu’à 10 secondes avant que les modifications soient reflétées dans les requêtes. L’API GetDigitalTwin (décrite plus loin dans cet article) ne subit pas ce délai. Utilisez l’appel d’API au lieu d’une interrogation pour voir vos nouveaux jumeaux créés si vous avez besoin d’une réponse instantanée.

Initialiser le modèle et les propriétés

Vous pouvez initialiser les propriétés d’un jumeau au moment de sa création.

L’API de création de jumeau accepte un objet qui est sérialisé dans une description JSON valide des propriétés du jumeau. Consultez Jumeaux numériques et graphe des jumeaux pour obtenir une description du format JSON d’un jumeau.

Tout d’abord, vous pouvez créer un objet de données pour représenter le jumeau et ses données de propriété. Vous pouvez créer un objet de paramètre manuellement ou à l’aide d’une classe d’assistance fournie. Voici un exemple de chaque méthode.

Créer des jumeaux à l’aide de données créées manuellement

Sans l’utilisation de classes d’assistance personnalisées, vous pouvez représenter les propriétés d’un jumeau dans un Dictionary<string, object>, où string est le nom de la propriété et object est un objet représentant la propriété et sa valeur.

// Define a custom model type for the twin to be created

internal class CustomDigitalTwin
{
    [JsonPropertyName(DigitalTwinsJsonPropertyNames.DigitalTwinId)]
    public string Id { get; set; }

    [JsonPropertyName(DigitalTwinsJsonPropertyNames.DigitalTwinETag)]
    public string ETag { get; set; }

    [JsonPropertyName("temperature")]
    public double Temperature { get; set; }

    [JsonPropertyName("humidity")]
    public double Humidity{ get; set; }
}

// Initialize properties and create the twin
public class TwinOperationsCreateTwin
{
    public async Task CreateTwinAsync(DigitalTwinsClient client)
    {
        // Initialize the twin properties
        var myTwin = new CustomDigitalTwin
        {
            Temperature = 25.0,
            Humidity = 50.0,
        };

        // Create the twin
        const string twinId = "<twin-ID>";
        Response<CustomDigitalTwin> response = await client.CreateOrReplaceDigitalTwinAsync(twinId, myTwin);
        Console.WriteLine($"Temperature value: {response.Value.Temperature}");
    }
}

Créer des jumeaux avec la classe d’assistance

La classe d’assistance de BasicDigitalTwin vous permet de stocker directement les champs de propriété dans un objet « jumeau ». Vous pouvez toujours créer la liste de propriétés à l’aide d’un Dictionary<string, object>, qui peut ensuite être ajouté directement à l’objet jumeau comme CustomProperties.

string twinId = "myTwinID";
var initData = new BasicDigitalTwin
{
    Id = twinId,
    Metadata = { ModelId = "dtmi:example:Room;1" },
    // Initialize properties
    Contents =
    {
        { "Temperature", 25.0 },
        { "Humidity", 50.0 },
    },
};

await client.CreateOrReplaceDigitalTwinAsync<BasicDigitalTwin>(twinId, initData);

Remarque

Les objets BasicDigitalTwin sont fournis avec un champ Id. Vous pouvez conserver ce champ vide, mais, si vous ajoutez une valeur d’ID, celle-ci doit correspondre au paramètre d’ID transmis à l’appel de CreateOrReplaceDigitalTwinAsync(). Par exemple :

twin.Id = "myRoomId";

Créer des jumeaux en bloc avec l’API Importer des travaux

Vous pouvez utiliser l’API Importer des travaux pour créer de nombreux jumeaux à la fois en un seul appel d’API. Cette méthode nécessite l’utilisation de Stockage Blob Azure et des autorisations d’écriture dans votre instance Azure Digital Twins pour les jumeaux et les travaux en bloc.

Conseil

L’API Importer des travaux permet également d’importer des modèles et des relations dans le même appel, afin de créer toutes les parties d’un graphique à la fois. Pour plus d’informations sur ce processus, consultez Charger des modèles, des jumeaux et des relations en bloc avec l’API Importer des travaux.

Pour importer des jumeaux en bloc, vous devez structurer vos jumeaux (et toutes les autres ressources incluses dans le travail d’importation en bloc) dans un fichier NDJSON. La section Twins vient après la section Models (et avant la section Relationships). Les jumeaux définis dans le fichier peuvent référencer des modèles définis dans ce fichier ou déjà présents dans l’instance, et ils peuvent éventuellement inclure l’initialisation des propriétés du jumeau.

Vous pouvez consulter un exemple de fichier d’importation et un exemple de projet pour la création de ces fichiers dans Présentation de l’API Importer des travaux.

Ensuite, le fichier doit être chargé dans un blob d’ajout dans le Stockage Blob Azure. Pour savoir comment créer un conteneur de Stockage Azure, consultez Créer un conteneur. Ensuite, chargez le fichier en utilisant votre méthode de chargement préférée (parmi les options vous avez la commande AzCopy, Azure CLI ou le portail Azure).

Une fois le fichier NDJSON chargé dans le conteneur, obtenez son URL dans le conteneur de blobs. Vous utilisez cette valeur plus loin dans le corps de l’appel d’API d’importation en bloc.

Voici une capture d’écran montrant la valeur d’URL d’un fichier de blob dans le portail Azure :

Capture d’écran du portail Azure montrant l’URL d’un fichier dans un conteneur de stockage.

Ensuite, le fichier peut être utilisé dans un appel de l’API Importer des travaux. Vous fournissez l’URL de stockage blob du fichier d’entrée, ainsi qu’une nouvelle URL de stockage blob pour indiquer où vous souhaitez stocker le journal de sortie une fois que le service l’a créé.

Obtenir des données pour un jumeau numérique

Vous pouvez accéder aux détails de n’importe quel jumeau numérique en appelant la méthode GetDigitalTwin() comme suit :

Response<BasicDigitalTwin> twinResponse = await client.GetDigitalTwinAsync<BasicDigitalTwin>(twinId);
twin = twinResponse.Value;

Cet appel retourne des données de jumeau sous forme de type d’objet fortement typé tel que BasicDigitalTwin. BasicDigitalTwin est une classe d’assistance de sérialisation incluse avec le Kit de développement logiciel (SDK), qui retourne les propriétés et les métadonnées de base du jumeau dans un format préalablement analysé. Vous pouvez toujours désérialiser des données de jumeau à l’aide de la bibliothèque JSON de votre choix, comme System.Text.Json ou Newtonsoft.Json. Toutefois, si vous avez besoin d’un accès de base à un jumeau, les classes d’assistance peuvent vous faciliter la tâche.

Remarque

BasicDigitalTwin utilise des attributs System.Text.Json. Pour pouvoir utiliser BasicDigitalTwin avec votre DigitalTwinsClient, vous devez initialiser le client avec le constructeur par défaut. Si vous voulez personnaliser l’option du sérialiseur, utilisez JsonObjectSerializer.

La classe d’assistance BasicDigitalTwin vous donne également accès aux propriétés définies dans le jumeau, par le biais d’un Dictionary<string, object>. Pour lister les propriétés du jumeau, vous pouvez utiliser ceci :

BasicDigitalTwin twin;
Response<BasicDigitalTwin> twinResponse = await client.GetDigitalTwinAsync<BasicDigitalTwin>(twinId);
twin = twinResponse.Value;
Console.WriteLine($"Model id: {twin.Metadata.ModelId}");
foreach (string prop in twin.Contents.Keys)
{
    if (twin.Contents.TryGetValue(prop, out object value))
        Console.WriteLine($"Property '{prop}': {value}");
}

Seules les propriétés qui ont été définies au moins une fois sont retournées lorsque vous récupérez un jumeau avec la méthode GetDigitalTwin().

Conseil

La displayName pour un jumeau est une partie de ses métadonnées de modèle, donc elle ne s’affichera pas lors de l’obtention de données pour l’instance jumelle. Pour afficher cette valeur, vous pouvez la récupérer à partir du modèle.

Pour récupérer plusieurs jumeaux avec un seul appel d’API, consultez les exemples d’API de requête dans Interroger le graphe de jumeaux.

Prenez pour exemple le modèle suivant (écrit en DTDL (Digital Twins Definition Language)) qui définit une Lune :

{
    "@id": "dtmi:example:Moon;1",
    "@type": "Interface",
    "@context": "dtmi:dtdl:context;3",
    "contents": [
        {
            "@type": "Property",
            "name": "radius",
            "schema": "double",
            "writable": true
        },
        {
            "@type": "Property",
            "name": "mass",
            "schema": "double",
            "writable": true
        }
    ]
}

Le résultat de l’appel de object result = await client.GetDigitalTwinAsync("my-moon"); sur un jumeau de type Lune peut se présenter comme suit :

{
  "$dtId": "myMoon-001",
  "$etag": "W/\"e59ce8f5-03c0-4356-aea9-249ecbdc07f9\"",
  "radius": 1737.1,
  "mass": 0.0734,
  "$metadata": {
    "$model": "dtmi:example:Moon;1",
    "radius": {
      "lastUpdateTime": "2022-12-06T20:00:32.8209188Z"
    },
    "mass": {
      "lastUpdateTime": "2022-12-04T12:04:43.3859361Z"
    }
  }
}

Les propriétés définies du jumeau numérique sont retournées en tant que propriétés de niveau supérieur sur le jumeau numérique. Les métadonnées ou les informations système qui ne font pas partie de la définition DTDL sont retournées avec un préfixe $. Les propriétés de métadonnées comprennent les valeurs suivantes :

  • $dtId : L’ID du jumeau numérique dans cette instance d’Azure Digital Twins
  • $etag : Un champ HTTP standard attribué par le serveur web. Sa valeur est mise à jour chaque fois que le jumeau est mis à jour, ce qui peut être utile pour déterminer si les données du jumeau ont été mises à jour sur le serveur depuis la vérification précédente. Vous pouvez utiliser If-Match pour effectuer des mises à jour et des suppressions qui se terminent uniquement si l’Etag de l’entité correspond à celui fourni. Pour plus d’informations sur ces opérations, consultez la documentation relative à DigitalTwins Update et à DigitalTwins Delete.
  • $metadata : ensemble de propriétés de métadonnées, qui peuvent inclure les éléments suivants :
    • $model, le DTMI du modèle du jumeau numérique.
    • lastUpdateTime pour les propriétés de jumeau. Il s’agit d’un horodatage indiquant la date et l’heure auxquelles Azure Digital Twins a traité le message de mise à jour de propriété.
    • sourceTime pour les propriétés de jumeau. Il s’agit d’une propriété facultative accessible en écriture qui représente la date et l’heure auxquelles la mise à jour de la propriété a été observée.

Vous pouvez en savoir plus sur les champs contenus dans un jumeau numérique dans Format JSON de jumeaux numériques. Pour plus d’informations sur les classes d’assistance de sérialisation comme BasicDigitalTwin, consultez API et SDK Azure Digital Twins.

Supprimer tous les jumeaux numériques

Pour afficher tous les représentations numériques présents dans votre instance, utilisez une requête. Vous pouvez exécuter une requête avec les API de requête ou les commandes CLI.

Voici le corps de la requête de base qui retourne la liste de tous les jumeaux numériques dans l’instance :

SELECT * FROM DIGITALTWINS

Mettre à jour un jumeau numérique

Pour mettre à jour les propriétés d’un jumeau numérique, écrivez les informations que vous souhaitez remplacer au format JSON Patch. Pour obtenir la liste complète des opérations JSON Patch que vous pouvez utiliser, y compris replace, add et remove, consultez la section Operations sur le site JSON Patch.

Après avoir créé le document JSON Patch contenant les informations de mise à jour, passez le document dans la méthode UpdateDigitalTwin() :

await client.UpdateDigitalTwinAsync(twinId, updateTwinData);

Un même appel de correctif peut mettre à jour autant de propriétés que vous le souhaitez (même toutes) sur un seul jumeau. Si vous devez mettre à jour des propriétés sur plusieurs jumeaux, vous avez besoin d’un appel de mise à jour distinct pour chaque jumeau.

Conseil

Après la création ou la mise à jour d’un jumeau, il peut y avoir une latence allant jusqu’à 10 secondes avant que les modifications soient reflétées dans les requêtes. L’API GetDigitalTwin (décrite plus loin dans cet article) ne subit pas ce délai. Utilisez l’appel d’API au lieu d’une interrogation pour voir vos jumeaux mis à jour si vous avez besoin d’une réponse instantanée.

Voici un exemple de code de correctif JSON. Ce document remplace les valeurs des propriétés masse et rayon du jumeau numérique auquel il est appliqué. Cet exemple montre l'opération replace JSON Patch, qui remplace la valeur d'une propriété existante.

[
    {
      "op": "replace",
      "path": "/mass",
      "value": 0.0799
    },
    {
      "op": "replace",
      "path": "/radius",
      "value": 0.800
    }
  ]

Lors de la mise à jour d'un jumeau à partir d'un projet de code utilisant le SDK .NET, vous pouvez créer des correctifs JSON à l'aide du JsonPatchDocument du SDK Azure .NET. Voici un exemple de création d’un document JSON Patch et d’utilisation de UpdateDigitalTwin() dans le code de projet.

var updateTwinData = new JsonPatchDocument();
updateTwinData.AppendAdd("/Temperature", 25.0);
updateTwinData.AppendAdd("/myComponent/Property", "Hello");
// Un-set a property
updateTwinData.AppendRemove("/Humidity");

await client.UpdateDigitalTwinAsync("myTwin", updateTwinData).ConfigureAwait(false);

Conseil

Vous pouvez conserver l’horodatage source de vos jumeaux numériques en mettant à jour le champ $metadata.<property-name>.sourceTime à l’aide du processus décrit dans cette section. Pour plus d’informations sur ce champ et sur les autres champs accessibles en écriture dans les jumeaux numériques, consultez Format JSON de jumeaux numériques.

Mettre à jour les sous-propriétés dans les composants des jumeaux numériques

Rappelez-vous qu’un modèle peut contenir des composants, ce qui lui permet d’être constitué d’autres modèles.

Pour corriger les propriétés dans les composants d’un jumeau numérique, vous pouvez utiliser la syntaxe du chemin dans le correctif JSON :

[
  {
    "op": "replace",
    "path": "/mycomponentname/mass",
    "value": 0.0799
  }
]

Mettre à jour les sous-propriétés dans les propriétés de type Object

Les modèles peuvent contenir des propriétés qui sont d’un type Object. Ces objets peuvent avoir leurs propres propriétés, et vous pouvez mettre à jour l’une de ces sous-propriétés appartenant à la propriété de type Object. Ce processus est similaire au processus de mise à jour des sous-propriétés dans les composants, mais peut nécessiter des étapes supplémentaires.

Prenons l’exemple d’un modèle avec une propriété de type Object, ObjectProperty. ObjectProperty a une propriété de chaîne nommée StringSubProperty.

Quand un jumeau est créé à l’aide de ce modèle, il n’est pas nécessaire d’instancier l’ObjectProperty à ce moment-là. Si la propriété d’objet n’est pas instanciée lors de la création d’un jumeau, aucun chemin par défaut n’est créé pour accéder à ObjectProperty et à sa StringSubProperty pour une opération de correctif. Vous devez ajouter le chemin à ObjectProperty vous-même avant de pouvoir mettre à jour ses propriétés.

Pour ce faire, vous pouvez utiliser une opération de correctif JSON add, comme suit :

[
  {
    "op": "add", 
    "path": "/ObjectProperty", 
    "value": {"StringSubProperty":"<string-value>"}
  }
]

Remarque

Si ObjectProperty a plusieurs propriétés, vous devez toutes les inclure dans le champ value de cette opération, même si vous n’en mettez qu’une seule à jour :

... "value": {"StringSubProperty":"<string-value>", "Property2":"<property2-value>", ...}

Une fois cette opération effectuée, il existe un chemin à StringSubProperty et il peut désormais être mis à jour directement avec une opération replace ordinaire :

[
  {
    "op": "replace",
    "path": "/ObjectProperty/StringSubProperty",
    "value": "<string-value>"
  }
]

Bien que la première étape ne soit pas nécessaire dans les cas où ObjectProperty a été instanciée lors de la création du jumeau, nous vous recommandons de l’utiliser chaque fois que vous mettez à jour une sous-propriété pour la première fois, car vous ne serez pas toujours certain que la propriété de l’objet a été instanciée initialement.

Mettre à jour le modèle d’un jumeau numérique

La fonction UpdateDigitalTwin() peut également être utilisée pour migrer un jumeau numérique vers un modèle différent.

Par exemple, examinez le document de correctif JSON suivant qui remplace le champ $model des métadonnées du jumeau numérique :

[
  {
    "op": "replace",
    "path": "/$metadata/$model",
    "value": "dtmi:example:foo;1"
  }
]

Cette opération réussit uniquement si le jumeau numérique modifié par le correctif est conforme au nouveau modèle.

Prenons l’exemple suivant :

  1. Imaginez un jumeau numérique avec un modèle foo_old. foo_old définit une propriété obligatoire, masse.
  2. Le nouveau modèle foo_new définit une propriété de masse et ajoute une nouvelle propriété obligatoire, température.
  3. Après le correctif, le jumeau numérique doit avoir une propriété de masse et de température.

Le correctif pour cette situation doit mettre à jour le modèle et la propriété de température du jumeau, comme suit :

[
  {
    "op": "replace",
    "path": "/$metadata/$model",
    "value": "dtmi:example:foo_new;1"
  },
  {
    "op": "add",
    "path": "/temperature",
    "value": 60
  }
]

Mettre à jour le sourceTime d’une propriété

Vous pouvez décider d’utiliser le champ sourceTime des propriétés de jumeaux pour enregistrer les horodatages lorsque des mises à jour de propriétés sont observées. Azure Digital Twins prend en charge sourceTime en mode natif dans les métadonnées de chaque propriété de jumeau. La valeur sourceTime doit être conforme au format de date et d’heure ISO 8601. Pour plus d’informations sur ce champ et sur les autres champs des jumeaux numériques, consultez Format JSON de jumeaux numériques.

La version stable minimale de l’API REST pour prendre en charge ce champ est la version 2022-05-31. Pour utiliser ce champ à l’aide des kits SDK Azure Digital Twins, nous vous recommandons d’utiliser la dernière version du kit SDK pour vous assurer que ce champ est inclus.

Voici un exemple de document JSON Patch qui met à jour la valeur et le champ sourceTime d’une propriété Temperature :

[
  {
    "op": "replace",
    "path": "/Temperature",
    "value": "22.3"
  },
  {
    "op": "replace",
    "path": "/$metadata/Temperature/sourceTime",
    "value": "2021-11-30T18:47:53.7648958Z"
  }
]

Pour mettre à jour le champ sourceTime dans une propriété qui fait partie d’un composant, incluez le composant au début du chemin. Dans l’exemple ci-dessus, vous le feriez en modifiant la valeur de chemin de /$metadata/Temperature/sourceTime en myComponent/$metadata/Temperature/sourceTime.

Remarque

Si vous mettez à jour la valeur et la sourceTime sur une propriété, puis mettez à jour ultérieurement la valeur de la propriété uniquement, l’horodatage sourceTime à partir de la première mise à jour restera.

Traiter les appels de mise à jour en conflit

Azure Digital Twins garantit que toutes les requêtes entrantes sont traitées l’une après l’autre. Cela signifie que même si plusieurs fonctions essaient de mettre à jour la même propriété sur un jumeau en même temps, il est inutile d’écrire un code de verrouillage explicite pour gérer le conflit.

Ce comportement se fait par jumeau.

Par exemple, imaginez un scénario dans lequel ces trois appels arrivent en même temps :

  • Écrire la propriété A sur Twin1
  • Écrire la propriété B sur Twin1
  • Écrire la propriété A sur Twin2

Les deux appels qui modifient Twin1 sont exécutés l’un après l’autre, et les messages de modification sont générés pour chaque modification. L’appel à modifier Twin2 peut être exécuté simultanément sans conflit, dès qu’il arrive.

Supprimer un jumeau numérique

Vous pouvez supprimer des jumeaux à l’aide de la méthode DeleteDigitalTwin(). Toutefois, vous ne pouvez supprimer un jumeau que s’il n’a plus de relations. Ainsi, supprimez d’abord les relations entrantes et sortantes du jumeau.

Voici un exemple de code permettant de supprimer des jumeaux et leurs relations. L’appel du kit SDK à DeleteDigitalTwin est mis en surbrillance pour clarifier son emplacement par rapport au contexte de l’exemple.

private static async Task CustomMethod_DeleteTwinAsync(DigitalTwinsClient client, string twinId)
{
    await CustomMethod_FindAndDeleteOutgoingRelationshipsAsync(client, twinId);
    await CustomMethod_FindAndDeleteIncomingRelationshipsAsync(client, twinId);
    try
    {
        await client.DeleteDigitalTwinAsync(twinId);
        Console.WriteLine("Twin deleted successfully");
    }
    catch (RequestFailedException ex)
    {
        Console.WriteLine($"*** Error:{ex.Message}");
    }
}

private static async Task CustomMethod_FindAndDeleteOutgoingRelationshipsAsync(DigitalTwinsClient client, string dtId)
{
    // Find the relationships for the twin

    try
    {
        // GetRelationshipsAsync will throw an error if a problem occurs
        AsyncPageable<BasicRelationship> rels = client.GetRelationshipsAsync<BasicRelationship>(dtId);

        await foreach (BasicRelationship rel in rels)
        {
            await client.DeleteRelationshipAsync(dtId, rel.Id).ConfigureAwait(false);
            Console.WriteLine($"Deleted relationship {rel.Id} from {dtId}");
        }
    }
    catch (RequestFailedException ex)
    {
        Console.WriteLine($"*** Error {ex.Status}/{ex.ErrorCode} retrieving or deleting relationships for {dtId} due to {ex.Message}");
    }
}

private static async Task CustomMethod_FindAndDeleteIncomingRelationshipsAsync(DigitalTwinsClient client, string dtId)
{
    // Find the relationships for the twin

    try
    {
        // GetRelationshipsAsync will throw an error if a problem occurs
        AsyncPageable<IncomingRelationship> incomingRels = client.GetIncomingRelationshipsAsync(dtId);

        await foreach (IncomingRelationship incomingRel in incomingRels)
        {
            await client.DeleteRelationshipAsync(incomingRel.SourceId, incomingRel.RelationshipId).ConfigureAwait(false);
            Console.WriteLine($"Deleted incoming relationship {incomingRel.RelationshipId} from {dtId}");
        }
    }
    catch (RequestFailedException ex)
    {
        Console.WriteLine($"*** Error {ex.Status}/{ex.ErrorCode} retrieving or deleting incoming relationships for {dtId} due to {ex.Message}");
    }
}

Supprimer tous les jumeaux numériques

Pour obtenir un exemple de suppression simultanée de tous les jumeaux numériques, téléchargez l’exemple d’application utilisé dans Explorer les bases avec un exemple d’application cliente. Le fichier CommandLoop.cs le fait dans une fonction CommandDeleteAllTwins().

Remarque

Si vous voulez supprimer tous les modèles, jumeaux et relations d’une instance à la fois, utilisez l’API Supprimer des travaux.

Exemple de code de jumeau numérique exécutable

Vous pouvez utiliser l’exemple de code exécutable ci-dessous pour créer un jumeau, mettre à jour ses détails et supprimer le jumeau.

Configurer des exemples de fichiers de projet

L’extrait de code utilise l’exemple de définition de modèle Room.json. Pour télécharger le fichier de modèle afin de l’utiliser dans votre code, utilisez ce lien pour accéder directement au fichier dans GitHub. Ensuite, cliquez avec le bouton droit n’importe où sur l’écran, sélectionnez Enregistrer sous dans le menu contextuel du navigateur, puis utilisez la fenêtre Enregistrer sous pour enregistrer le fichier sous le nom Room.json.

Ensuite, créez un projet d’application console dans Visual Studio ou l’éditeur de votre choix.

Puis, copiez le code suivant de l’exemple exécutable dans votre projet :

using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using Azure;
using Azure.DigitalTwins.Core;
using Azure.Identity;
using System.IO;

namespace DigitalTwins_Samples
{
    class TwinOperationsSample
    {
        public static async Task Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            // Create the Azure Digital Twins client for API calls
            string adtInstanceUrl = "https://<your-instance-hostname>";
            var credentials = new DefaultAzureCredential();
            var client = new DigitalTwinsClient(new Uri(adtInstanceUrl), credentials);
            Console.WriteLine($"Service client created – ready to go");

            // Upload models
            Console.WriteLine($"Upload a model");
            string dtdl = File.ReadAllText("<path-to>/Room.json");
            var models = new List<string> { dtdl };
            // Upload the model to the service
            await client.CreateModelsAsync(models);

            // Create new digital twin
            // <CreateTwin_withHelper>
            string twinId = "myTwinID";
            var initData = new BasicDigitalTwin
            {
                Id = twinId,
                Metadata = { ModelId = "dtmi:example:Room;1" },
                // Initialize properties
                Contents =
                {
                    { "Temperature", 25.0 },
                    { "Humidity", 50.0 },
                },
            };

            // <CreateTwinCall>
            await client.CreateOrReplaceDigitalTwinAsync<BasicDigitalTwin>(twinId, initData);
            // </CreateTwinCall>
            // </CreateTwin_withHelper>
            Console.WriteLine("Twin created successfully");

            //Print twin
            Console.WriteLine("--- Printing twin details:");
            await CustomMethod_FetchAndPrintTwinAsync(twinId, client);
            Console.WriteLine("--------");

            //Update twin data
            var updateTwinData = new JsonPatchDocument();
            updateTwinData.AppendAdd("/Temperature", 30.0);
            // <UpdateTwinCall>
            await client.UpdateDigitalTwinAsync(twinId, updateTwinData);
            // </UpdateTwinCall>
            Console.WriteLine("Twin properties updated");
            Console.WriteLine();

            //Print twin again
            Console.WriteLine("--- Printing twin details (after update):");
            await CustomMethod_FetchAndPrintTwinAsync(twinId, client);
            Console.WriteLine("--------");
            Console.WriteLine();

            //Delete twin
            await CustomMethod_DeleteTwinAsync(client, twinId);
        }

        private static async Task<BasicDigitalTwin> CustomMethod_FetchAndPrintTwinAsync(string twinId, DigitalTwinsClient client)
        {
            // <GetTwin>
            BasicDigitalTwin twin;
            // <GetTwinCall>
            Response<BasicDigitalTwin> twinResponse = await client.GetDigitalTwinAsync<BasicDigitalTwin>(twinId);
            twin = twinResponse.Value;
            // </GetTwinCall>
            Console.WriteLine($"Model id: {twin.Metadata.ModelId}");
            foreach (string prop in twin.Contents.Keys)
            {
                if (twin.Contents.TryGetValue(prop, out object value))
                    Console.WriteLine($"Property '{prop}': {value}");
            }
            // </GetTwin>

            return twin;
        }

        // <DeleteTwin>
        private static async Task CustomMethod_DeleteTwinAsync(DigitalTwinsClient client, string twinId)
        {
            await CustomMethod_FindAndDeleteOutgoingRelationshipsAsync(client, twinId);
            await CustomMethod_FindAndDeleteIncomingRelationshipsAsync(client, twinId);
            try
            {
                await client.DeleteDigitalTwinAsync(twinId);
                Console.WriteLine("Twin deleted successfully");
            }
            catch (RequestFailedException ex)
            {
                Console.WriteLine($"*** Error:{ex.Message}");
            }
        }

        private static async Task CustomMethod_FindAndDeleteOutgoingRelationshipsAsync(DigitalTwinsClient client, string dtId)
        {
            // Find the relationships for the twin

            try
            {
                // GetRelationshipsAsync will throw an error if a problem occurs
                AsyncPageable<BasicRelationship> rels = client.GetRelationshipsAsync<BasicRelationship>(dtId);

                await foreach (BasicRelationship rel in rels)
                {
                    await client.DeleteRelationshipAsync(dtId, rel.Id).ConfigureAwait(false);
                    Console.WriteLine($"Deleted relationship {rel.Id} from {dtId}");
                }
            }
            catch (RequestFailedException ex)
            {
                Console.WriteLine($"*** Error {ex.Status}/{ex.ErrorCode} retrieving or deleting relationships for {dtId} due to {ex.Message}");
            }
        }

        private static async Task CustomMethod_FindAndDeleteIncomingRelationshipsAsync(DigitalTwinsClient client, string dtId)
        {
            // Find the relationships for the twin

            try
            {
                // GetRelationshipsAsync will throw an error if a problem occurs
                AsyncPageable<IncomingRelationship> incomingRels = client.GetIncomingRelationshipsAsync(dtId);

                await foreach (IncomingRelationship incomingRel in incomingRels)
                {
                    await client.DeleteRelationshipAsync(incomingRel.SourceId, incomingRel.RelationshipId).ConfigureAwait(false);
                    Console.WriteLine($"Deleted incoming relationship {incomingRel.RelationshipId} from {dtId}");
                }
            }
            catch (RequestFailedException ex)
            {
                Console.WriteLine($"*** Error {ex.Status}/{ex.ErrorCode} retrieving or deleting incoming relationships for {dtId} due to {ex.Message}");
            }
        }
        // </DeleteTwin>

    }
}

Remarque

Il existe actuellement un problème connu affectant la classe wrapper DefaultAzureCredential susceptible d’entraîner une erreur lors de l’authentification. Si vous rencontrez ce problème, vous pouvez essayer d’instancier DefaultAzureCredential avec le paramètre facultatif suivant afin de le résoudre : new DefaultAzureCredential(new DefaultAzureCredentialOptions { ExcludeSharedTokenCacheCredential = true });

Pour plus d’informations sur ce problème, consultez Problèmes connus d’Azure Digital Twins.

Configurer un projet

Ensuite, effectuez les étapes ci-après pour configurer votre code de projet :

  1. Ajoutez le fichier Room.json que vous avez téléchargé précédemment à votre projet et remplacez l’espace réservé <path-to> dans le code pour indiquer à votre programme où le trouver.

  2. Remplacez l’espace réservé <your-instance-hostname> par le nom d’hôte de votre instance Azure Digital Twins.

  3. Ajoutez deux dépendances à votre projet. Elles sont nécessaires pour travailler avec Azure Digital Twins. La première correspond au package pour le SDK Azure Digital Twins pour .NET, et la seconde fournit des outils facilitant l’authentification auprès d’Azure.

    dotnet add package Azure.DigitalTwins.Core
    dotnet add package Azure.Identity
    

Vous devez également configurer des informations d’identification locales si vous souhaitez exécuter l’exemple directement. La section suivante décrit cette procédure.

Configurer les informations d’identification Azure locales

Cet exemple utilise DefaultAzureCredential (qui fait partie de la bibliothèque Azure.Identity) pour authentifier les utilisateurs auprès de l’instance Azure Digital Twins quand vous l’exécutez sur votre ordinateur local. Pour plus d’informations sur les différentes façons dont une application cliente peut s’authentifier auprès d’Azure Digital Twins, consultez Écrire le code d’authentification de l’application.

Avec DefaultAzureCredential, l’exemple recherche les informations d’identification dans votre environnement local, comme une connexion Azure dans une interface de ligne de commande Azure locale ou dans Visual Studio ou Visual Studio Code. C’est la raison pour laquelle vous devez vous connecter à Azure localement via l’un de ces mécanismes afin de configurer les informations d’identification pour l’exemple.

Si vous utilisez Visual Studio ou Visual Studio Code pour exécuter des exemples de code, vérifiez que vous êtes connecté à cet éditeur avec les mêmes informations d’identification Azure que celles que vous souhaitez utiliser pour accéder à votre instance Azure Digital Twins. Si vous utilisez une fenêtre CLI locale, exécutez la commande az login pour vous connecter à votre compte Azure. Après cela, lorsque vous exécutez votre échantillon de code, vous devriez être authentifié automatiquement.

Exécution de l'exemple

Maintenant que la configuration est terminée, vous pouvez exécuter l’exemple de projet de code.

Voici la sortie de la console du programme ci-dessus :

Capture d’écran de la sortie de la console indiquant que le jumeau est créé, mis à jour et supprimé.

Étapes suivantes

Découvrez comment créer et gérer des relations entre vos jumeaux numériques :