Verwalten eines Graphen von digitalen Zwillingen mithilfe von Beziehungen

Das Herzstück von Azure Digital Twins ist der Zwillingsgraph, der Ihre gesamte Umgebung darstellt. Der Zwillingsgraph besteht aus einzelnen digitalen Zwillingen, die über Beziehungen miteinander verbunden sind. Dieser Artikel konzentriert sich auf die Verwaltung von Beziehungen und den Graphen als Ganzes. Für die Arbeit mit einzelnen digitalen Zwillingen finden Sie weitere Informationen unter Verwalten digitaler Zwillinge.

Wenn Sie über eine funktionierende Azure Digital Twins-Instanz verfügen und Code zur Authentifizierung in Ihrer Client-App eingerichtet haben, können Sie digitale Zwillinge und ihre Beziehungen in einer Azure Digital Twins-Instanz erstellen, ändern und löschen.

Voraussetzungen

Damit Sie in diesem Artikel mit Azure Digital Twins arbeiten können, benötigen Sie eine Azure Digital Twins-Instanz und die erforderlichen Berechtigungen, um sie zu verwenden. Wenn Sie über eine bereits eingerichtete Azure Digital Twins-Instanz verfügen, können Sie diese nutzen und zum nächsten Abschnitt springen. Befolgen Sie andernfalls die Anleitung unter Einrichten einer Instanz und der Authentifizierung. Die Anweisungen enthalten Informationen, mit denen Sie überprüfen können, ob jeder Schritt erfolgreich abgeschlossen wurde.

Notieren Sie sich nach dem Einrichten Ihrer Instanz den Hostnamen der Instanz. Sie finden den Hostnamen im Azure-Portal.

Entwicklerschnittstellen

In diesem Artikel wird erläutert, wie Sie unterschiedliche Verwaltungsvorgänge mithilfe des .NET (C#) SDK durchführen. Sie können dieselben Verwaltungsaufrufe auch mit den anderen Sprach-SDKs erstellen, wie unter Azure Digital Twins-APIs und SDKs beschrieben.

Andere Entwicklerschnittstellen, die zum Ausführen dieser Vorgänge verwendet werden können, sind:

Visualisierung

Der Azure Digital Twins-Explorer ist ein visuelles Tool zum Untersuchen der Daten in Ihrem Azure Digital Twins-Graphen. Mit dem Explorer können Sie Modelle, Zwillinge und Beziehungen anzeigen, abfragen und bearbeiten.

Weitere Informationen zum Azure Digital Twins-Explorer finden Sie unter Azure Digital Twins-Explorer. Ausführliche Schritte zur Verwendung der einzelnen Features finden Sie unter Verwenden von Azure Digital Twins-Explorer.

Die Visualisierung sieht wie folgt aus:

Screenshot of Azure Digital Twins Explorer showing sample models and twins.

Erstellen von Beziehungen

Beziehungen beschreiben, wie verschiedene digitale Zwillinge miteinander verbunden sind, was die Grundlage des Zwillingsgraphen bildet.

Die Arten von Beziehungen, die von einem (Quell-)Zwilling zu einem anderen (Ziel-)Zwilling hergestellt werden können, werden als Teil des DTDL-Modells des Quellzwillings definiert. Sie können eine Instanz einer Beziehung erstellen, indem Sie den SDK-Aufruf CreateOrReplaceRelationshipAsync() mit Zwillingen und Beziehungsdetails verwenden, die der DTDL-Definition entsprechen.

Sie müssen Folgendes angeben, um eine Beziehung zu erstellen:

  • Die Quell-Twin-ID (srcId im folgenden Codebeispiel): Die ID des Zwillings, in dem die Beziehung entsteht.
  • Die Ziel-Twin-ID (targetId im folgenden Codebeispiel): Die ID des Zwillings, bei dem die Beziehung eingeht.
  • Ein Beziehungsname (relName im untenstehenden Codebeispiel): Der generische Typ der Beziehung, etwa enthält.
  • Eine Beziehungs-ID (relId im untenstehenden Codebeispiel): Der spezifische Name für diese Beziehung, etwa Beziehung1.

Die Beziehungs-ID muss innerhalb des angegebenen Quellzwillings eindeutig sein. Sie muss nicht global eindeutig sein. Für den Zwilling „Foo“ muss z. B. jede bestimmte Beziehungs-ID eindeutig sein. Ein weiterer Zwilling „Bar“ kann jedoch eine ausgehende Beziehung aufweisen, die derselben ID einer Beziehung mit „Foo“ entspricht.

Im folgenden Codebeispiel wird veranschaulicht, wie Sie in Ihrer Azure Digital Twins-Instanz eine Beziehung erstellen. Der SDK-Aufruf (hervorgehoben) innerhalb einer benutzerdefinierten Methode wird verwendet, die im Kontext eines größeren Programms angezeigt werden kann.

private async static Task CustomMethod_CreateRelationshipAsync(DigitalTwinsClient client, string srcId, string targetId, string relName, IDictionary<string,object> inputProperties)
{
    var relationship = new BasicRelationship
    {
        TargetId = targetId,
        Name = relName,
        Properties = inputProperties
    };

    try
    {
        string relId = $"{srcId}-{relName}->{targetId}";
        await client.CreateOrReplaceRelationshipAsync<BasicRelationship>(srcId, relId, relationship);
        Console.WriteLine($"Created {relName} relationship successfully. Relationship ID is {relId}.");
    }
    catch (RequestFailedException rex)
    {
        Console.WriteLine($"Create relationship error: {rex.Status}:{rex.Message}");
    }

}

Diese benutzerdefinierte Funktion kann nun aufgerufen werden, um folgendermaßen eine contains-Beziehung zu erstellen:

await CustomMethod_CreateRelationshipAsync(client, srcId, targetId, "contains", properties);

Wenn Sie mehrere Beziehungen erstellen möchten, können Sie Aufrufe derselben Methode wiederholen und dabei verschiedene Beziehungstypen an das Argument übergeben.

Weitere Informationen zur Hilfsklasse BasicRelationship finden Sie unter Azure Digital Twins-APIs und -SDKs.

Erstellen mehrerer Beziehungen zwischen Zwillingen

Beziehungen können wie folgt klassifiziert werden:

  • Ausgehende Beziehungen: Beziehungen, die zu diesem Zwilling gehören, die nach außen gerichtet sind, um eine Verbindung mit anderen Zwillingen herzustellen. Die Methode GetRelationshipsAsync() wird verwendet, um ausgehende Beziehungen eines Zwillings abzurufen.
  • Eingehende Beziehungen: Beziehungen, die zu anderen Zwillingen gehören, die auf diesen Zwilling verweisen, um eine „eingehende“ Verbindung zu erstellen. Die Methode GetIncomingRelationshipsAsync() wird verwendet, um eingehende Beziehungen eines Zwillings abzurufen.

Zwischen Zwillingen können beliebig viele Beziehungen eingerichtet sein.

Das bedeutet, Sie können gleichzeitig verschiedene Arten von Beziehungen zwischen zwei Zwillingen ausdrücken. So kann z. B. Zwilling A sowohl eine gespeicherte als auch eine erstellte Beziehung mit Zwilling B haben.

Sie können bei Bedarf sogar mehrere Instanzen desselben Beziehungstyps zwischen zwei Zwillingen erstellen. In diesem Beispiel könnte Zwilling A zwei verschiedene gespeicherte Beziehungen mit Zwilling B aufweisen, solange die Beziehungen unterschiedliche Beziehungs-IDs verwenden.

Hinweis

Die DTDL-Attribute minMultiplicity und maxMultiplicity für Beziehungen werden derzeit in Azure Digital Twins nicht unterstützt – Selbst wenn sie als Teil eines Modells definiert sind, werden sie vom Dienst nicht erzwungen. Weitere Informationen finden Sie unter Dienstspezifische DTDL-Notizen.

Erstellen von Beziehungen in Massen mit der Importaufträge-API

Sie können die Importaufträge-API verwenden, um viele Beziehungen gleichzeitig in einem einzelnen API-Aufruf zu erstellen. Diese Methode erfordert die Verwendung von Azure Blob Storage sowie Schreibberechtigungen in Ihrer Azure Digital Twins-Instanz für Beziehungen und Massenaufträge.

Tipp

Die Importaufträge-API ermöglicht außerdem das Importieren von Modellen und Zwillingen im selben Aufruf, um alle Teile eines Diagramms gleichzeitig zu erstellen. Weitere Informationen zu diesem Prozess finden Sie unter Hochladen von Modellen, Zwillingen und Beziehungen in Massen mit der Importaufträge-API.

Um Beziehungen in Massen zu importieren, müssen Sie Ihre Beziehungen (und alle anderen Ressourcen, die im Massenimportauftrag enthalten sind) als NDJSON-Datei strukturieren. Der Relationships Abschnitt folgt nach dem Twins Abschnitt, wodurch er zum letzten Diagrammdatenabschnitt in der Datei wird. Beziehungen, die in der Datei definiert sind, können auf Zwillinge verweisen, die entweder in dieser Datei definiert oder bereits in der Instanz vorhanden sind, und sie können optional die Initialisierung aller Eigenschaften einschließen, die die Beziehungen aufweisen.

Sie können eine Beispielimportdatei und ein Beispielprojekt zum Erstellen dieser Dateien in der Einführung der Importaufträge-API anzeigen.

Als Nächstes muss die Datei in ein Anfüge-Blob in Azure Blob Storage hochgeladen werden. Anweisungen zum Erstellen eines Azure-Speichercontainers finden Sie unter Erstellen eines Containers. Laden Sie dann die Datei mit Ihrer bevorzugten Uploadmethode hoch (einige Optionen sind der AzCopy-Befehl, die Azure CLI oder die Azure-Portal).

Nachdem die NDJSON-Datei in den Container hochgeladen wurde, rufen Sie die URL im BLOB-Container ab. Sie verwenden diesen Wert später im Textkörper des API-Massenimportaufrufs.

Hier ist ein Screenshot, der den URL-Wert einer BLOB-Datei in der Azure-Portal zeigt:

Screenshot of the Azure portal showing the URL of a file in a storage container.

Anschließend kann die Datei in einem Importaufträge-API-Aufruf verwendet werden. Sie geben die BLOB-Speicher-URL der Eingabedatei sowie eine neue BLOB-Speicher-URL an, um anzugeben, wo das Ausgabeprotokoll gespeichert werden soll, wenn es vom Dienst erstellt wird.

Auflisten von Beziehungen

Auflisten der Eigenschaften einer einzelnen Beziehung

Beziehungsdaten können jederzeit in einen Typ Ihrer Wahl deserialisiert werden. Verwenden Sie für grundlegenden Zugriff auf eine Beziehung den Typ BasicRelationship. Die Hilfsklasse BasicRelationship bietet Ihnen über ein IDictionary<string, object>-Element auch Zugriff auf Eigenschaften, die für die Beziehung definiert sind. Zum Auflisten von Eigenschaften können Sie Folgendes verwenden:

public async Task ListRelationshipProperties(DigitalTwinsClient client, string twinId, string relId, BasicDigitalTwin twin)
{

    var res = await client.GetRelationshipAsync<BasicRelationship>(twinId, relId);
    BasicRelationship rel = res.Value;
    Console.WriteLine($"Relationship Name: {rel.Name}");
    foreach (string prop in rel.Properties.Keys)
    {
        if (twin.Contents.TryGetValue(prop, out object value))
        {
            Console.WriteLine($"Property '{prop}': {value}");
        }
    }
}

Auflisten der ausgehenden Beziehungen für einen digitalen Zwilling

Sie können die Methode GetRelationships() wie folgt verwenden, um auf die Liste der ausgehenden Beziehungen für einen bestimmten Zwilling im Graphen zuzugreifen:

AsyncPageable<BasicRelationship> rels = client.GetRelationshipsAsync<BasicRelationship>(dtId);

Diese Methode gibt Azure.Pageable<T> oder Azure.AsyncPageable<T> zurück, je nachdem, ob Sie die synchrone oder asynchrone Version des Aufrufs verwenden.

Nachstehend finden Sie ein Beispiel, das eine Liste von Beziehungen abruft. Der SDK-Aufruf (hervorgehoben) innerhalb einer benutzerdefinierten Methode wird verwendet, die im Kontext eines größeren Programms angezeigt werden kann.

private static async Task<List<BasicRelationship>> CustomMethod_FindOutgoingRelationshipsAsync(DigitalTwinsClient client, string dtId)
{
    // Find the relationships for the twin
    
    try
    {
        // GetRelationshipsAsync will throw if an error occurs
        AsyncPageable<BasicRelationship> rels = client.GetRelationshipsAsync<BasicRelationship>(dtId);
        var results = new List<BasicRelationship>();
        await foreach (BasicRelationship rel in rels)
        {
            results.Add(rel);
            Console.WriteLine($"Found relationship: {rel.Id}");

            //Print its properties
            Console.WriteLine($"Relationship properties:");
            foreach(KeyValuePair<string, object> property in rel.Properties)
            {
                Console.WriteLine("{0} = {1}", property.Key, property.Value);
            }
        }

        return results;
    }
    catch (RequestFailedException ex)
    {
        Console.WriteLine($"*** Error {ex.Status}/{ex.ErrorCode} retrieving relationships for {dtId} due to {ex.Message}");
        return null;
    }
}

Sie können diese benutzerdefinierte Methode jetzt aufrufen, um die ausgehenden Beziehungen der Zwillinge wie folgt anzuzeigen:

await CustomMethod_FindOutgoingRelationshipsAsync(client, twin_Id);

Sie können anhand der abgerufenen Beziehungen zu anderen Zwillingen in Ihrem Diagramm navigieren, indem Sie die Informationen im Feld target der zurückgegebenen Beziehung auslesen und als ID für den nächsten Aufruf von GetDigitalTwin() verwenden.

Auflisten von eingehenden Beziehungen für einen digitalen Zwilling

Azure Digital Twins verfügt außerdem über ein SDK, mit dem alle eingehenden Beziehungen für einen bestimmten Zwilling ermittelt werden können. Dieses SDK ist oft nützlich bei der umgekehrten Navigation oder beim Löschen eines Zwillings.

Hinweis

IncomingRelationship-Aufrufe geben nicht den vollständigen Text der Beziehung zurück. Weitere Informationen finden Sie in der Referenzdokumentation zur IncomingRelationship-Klasse.

Das Codebeispiel oben hat sich auf die Suche nach ausgehenden Beziehungen eines Zwillings konzentriert. Das folgende Beispiel ist ähnlich strukturiert, findet aber stattdessen eingehende Beziehungen vom Zwilling. Für dieses Beispiel wird auch der SDK-Aufruf (hervorgehoben) innerhalb einer benutzerdefinierten Methode verwendet, die im Kontext eines größeren Programms angezeigt werden kann.

private static async Task<List<IncomingRelationship>> CustomMethod_FindIncomingRelationshipsAsync(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);

        var results = new List<IncomingRelationship>();
        await foreach (IncomingRelationship incomingRel in incomingRels)
        {
            results.Add(incomingRel);
            Console.WriteLine($"Found incoming relationship: {incomingRel.RelationshipId}");

            //Print its properties
            Response<BasicRelationship> relResponse = await client.GetRelationshipAsync<BasicRelationship>(incomingRel.SourceId, incomingRel.RelationshipId);
            BasicRelationship rel = relResponse.Value;
            Console.WriteLine($"Relationship properties:");
            foreach(KeyValuePair<string, object> property in rel.Properties)
            {
                Console.WriteLine("{0} = {1}", property.Key, property.Value);
            }
        }
        return results;
    }
    catch (RequestFailedException ex)
    {
        Console.WriteLine($"*** Error {ex.Status}/{ex.ErrorCode} retrieving incoming relationships for {dtId} due to {ex.Message}");
        return null;
    }
}

Sie können diese benutzerdefinierte Methode jetzt aufrufen, um die eingehenden Beziehungen der Zwillinge wie folgt anzuzeigen:

await CustomMethod_FindIncomingRelationshipsAsync(client, twin_Id);

Auflisten aller Zwillingseigenschaften und -beziehungen

Mithilfe der oben genannten Methoden zur Auflistung der aus- und eingehenden Beziehungen zu einem Zwilling können Sie eine Methode erstellen, die vollständige Zwillingsinformationen ausgibt, einschließlich der Eigenschaften des Zwillings und beider Arten seiner Beziehungen. Hier finden Sie eine benutzerdefinierte Beispielmethode, die zeigt, wie Sie die obigen Methoden zu diesem Zweck kombinieren.

private static async Task CustomMethod_FetchAndPrintTwinAsync(string twin_Id, DigitalTwinsClient client)
{
    Response<BasicDigitalTwin> res = await client.GetDigitalTwinAsync<BasicDigitalTwin>(twin_Id);
    await CustomMethod_FindOutgoingRelationshipsAsync(client, twin_Id);
    await CustomMethod_FindIncomingRelationshipsAsync(client, twin_Id);

    return;
}

Sie können nun diese benutzerdefinierte Funktion wie folgt aufrufen:

await CustomMethod_FetchAndPrintTwinAsync(srcId, client);

Aktualisieren von Beziehungen

Beziehungen werden mit der UpdateRelationship-Methode aktualisiert.

Hinweis

Diese Methode dient zur Aktualisierung der Eigenschaften einer Beziehung. Wenn Sie den Quellzwilling oder den Zielzwilling der Beziehung ändern müssen, müssen Sie die Beziehung löschen und mithilfe der neuen Zwillinge eine neue erstellen.

Die erforderlichen Parameter für den Clientaufruf lauten folgendermaßen:

  • Die ID des Quellzwillings (der Zwilling, von dem die Beziehung ausgeht).
  • Die ID des Beziehungsobjekts, das aktualisiert werden soll.
  • Ein JSON-Patch-Dokument, das die Eigenschaften und neuen Werte enthält, die Sie aktualisieren möchten.

Hier sehen Sie einen beispielhaften Codeausschnitt, der die Verwendung dieser Methode zeigt. Für dieses Beispiel wird der SDK-Aufruf (hervorgehoben) innerhalb einer benutzerdefinierten Methode verwendet, die im Kontext eines größeren Programms angezeigt werden kann.

private async static Task CustomMethod_UpdateRelationshipAsync(DigitalTwinsClient client, string srcId, string relId, Azure.JsonPatchDocument updateDocument)
{

    try
    {
        await client.UpdateRelationshipAsync(srcId, relId, updateDocument);
        Console.WriteLine($"Successfully updated {relId}");
    }
    catch (RequestFailedException rex)
    {
        Console.WriteLine($"Update relationship error: {rex.Status}:{rex.Message}");
    }

}

Nachfolgend sehen Sie einen Beispielaufruf dieser benutzerdefinierten Methode. Darin wird ein JSON-Patch-Dokument mit den Informationen zur Aktualisierung einer Eigenschaft übergeben.

var updatePropertyPatch = new JsonPatchDocument();
updatePropertyPatch.AppendAdd("/ownershipUser", "ownershipUser NEW value");
await CustomMethod_UpdateRelationshipAsync(client, srcId, $"{srcId}-contains->{targetId}", updatePropertyPatch);

Beziehungen löschen

Der erste Parameter gibt den Quellzwilling an (der Zwilling, von dem die Beziehung ausgeht). Der andere Parameter ist die Beziehungs-ID. Sie benötigen sowohl die Zwillings-ID als auch die Beziehungs-ID, da Beziehungs-IDs nur innerhalb des Bereichs eines Zwillings eindeutig sind.

Hier sehen Sie Beispielcode, der die Verwendung dieser Methode zeigt. Für dieses Beispiel wird der SDK-Aufruf (hervorgehoben) innerhalb einer benutzerdefinierten Methode verwendet, die im Kontext eines größeren Programms angezeigt werden kann.

private static async Task CustomMethod_DeleteRelationshipAsync(DigitalTwinsClient client, string srcId, string relId)
{
    try
    {
        Response response = await client.DeleteRelationshipAsync(srcId, relId);
        await CustomMethod_FetchAndPrintTwinAsync(srcId, client);
        Console.WriteLine("Deleted relationship successfully");
    }
    catch (RequestFailedException e)
    {
        Console.WriteLine($"Error {e.ErrorCode}");
    }
}

Sie können jetzt diese benutzerdefinierte Methode aufrufen, um eine Beziehung wie folgt zu löschen:

await CustomMethod_DeleteRelationshipAsync(client, srcId, $"{srcId}-contains->{targetId}");

Hinweis

Wenn Sie alle Modelle, Zwillinge und Beziehungen in einer Instanz gleichzeitig löschen möchten, verwenden Sie die Delete Jobs-API.

Gleichzeitiges Erstellen mehrerer Diagrammelemente

In diesem Abschnitt werden Strategien zum Gleichzeitigen Erstellen eines Diagramms mit mehreren Elementen beschrieben, anstatt einzelne API-Aufrufe zum Hochladen von Modellen, Zwillingen und Beziehungen zum Hochladen von Modellen, Zwillingen und Beziehungen zu verwenden, um sie einzeln hochzuladen.

Hochladen von Modellen, Zwillingen und Beziehungen in Massen mit der Importaufträge-API

Sie können die Importaufträge-API verwenden, um mehrere Modelle, Zwillinge und Beziehungen in Eine Instanz in einem einzigen API-Aufruf hochzuladen und das Diagramm auf einmal zu erstellen. Diese Methode erfordert die Verwendung von Azure Blob Storage sowie Schreibberechtigungen in Ihrer Azure Digital Twins-Instanz für Diagrammelemente (Modelle, Zwillinge und Beziehungen) und Massenaufträge.

Um Ressourcen in Massen zu importieren, erstellen Sie zunächst eine NDJSON-Datei mit den Details Ihrer Ressourcen. Die Datei beginnt mit einem Header Abschnitt, gefolgt von den optionalen Abschnitten Models, Twinsund Relationships. Sie müssen nicht alle drei Arten von Diagrammdaten in die Datei einschließen, aber alle vorhandenen Abschnitte müssen dieser Reihenfolge entsprechen. Zwillinge, die in der Datei definiert sind, können auf Modelle verweisen, die entweder in dieser Datei definiert sind oder bereits in der Instanz vorhanden sind, und sie können optional die Initialisierung der Eigenschaften des Zwillings einschließen. Beziehungen, die in der Datei definiert sind, können auf Zwillinge verweisen, die entweder in dieser Datei definiert oder bereits in der Instanz vorhanden sind, und sie können optional die Initialisierung von Beziehungseigenschaften einschließen.

Sie können eine Beispielimportdatei und ein Beispielprojekt zum Erstellen dieser Dateien in der Einführung der Importaufträge-API anzeigen.

Als Nächstes muss die Datei in ein Anfüge-Blob in Azure Blob Storage hochgeladen werden. Anweisungen zum Erstellen eines Azure-Speichercontainers finden Sie unter Erstellen eines Containers. Laden Sie dann die Datei mit Ihrer bevorzugten Uploadmethode hoch (einige Optionen sind der AzCopy-Befehl, die Azure CLI oder die Azure-Portal).

Nachdem die NDJSON-Datei in den Container hochgeladen wurde, rufen Sie die URL im BLOB-Container ab. Sie verwenden diesen Wert später im Textkörper des API-Massenimportaufrufs.

Hier ist ein Screenshot, der den URL-Wert einer BLOB-Datei in der Azure-Portal zeigt:

Screenshot of the Azure portal showing the URL of a file in a storage container.

Anschließend kann die Datei in einem Importaufträge-API-Aufruf verwendet werden. Sie geben die BLOB-Speicher-URL der Eingabedatei sowie eine neue BLOB-Speicher-URL an, um anzugeben, wo das Ausgabeprotokoll gespeichert werden soll, wenn es vom Dienst erstellt wird.

Importieren von Diagrammen mit Azure Digital Twins Explorer

Azure Digital Twins Explorer ist ein visuelles Tool zum Anzeigen und Interagieren mit Ihrem Zwillingsdiagramm. Sie enthält ein Feature zum Importieren einer Diagrammdatei im JSON- oder Excel-Format, das mehrere Modelle, Zwillinge und Beziehungen enthalten kann.

Ausführliche Informationen zur Verwendung dieses Features finden Sie in der Dokumentation zum Azure Digital Twins Explorer.For detailed information about using this feature, see Import graph in the Azure Digital Twins Explorer documentation.

Erstellen von Zwillingen und Beziehungen aus einer CSV-Datei

Manchmal müssen Sie möglicherweise zwei Hierarchien aus Daten erstellen, die in einer anderen Datenbank oder in einer Kalkulationstabelle oder einer CSV-Datei gespeichert sind. In diesem Abschnitt wird gezeigt, wie Sie Daten aus einer CSV-Datei lesen und einen Zwillingsgraphen daraus erstellen.

Betrachten Sie die folgende Datentabelle, in der eine Reihe von digitalen Zwillingen und Beziehungen beschrieben werden. Die in dieser Datei referenzierten Modelle müssen bereits in der Azure Digital Twins-Instanz vorhanden sein.

Modell-ID Zwillings-ID (muss eindeutig sein) Beziehungsname Zielzwillings-ID Initialisierungsdaten des Zwillings
dtmi:example:Floor;1 Floor1 contains Room1
dtmi:example:Floor;1 Floor0 contains Room0
dtmi:example:Room;1 Room1 {"Temperature": 80}
dtmi:example:Room;1 Room0 {"Temperature": 70}

Eine Möglichkeit zum Übernehmen dieser Daten in Azure Digital Twins besteht darin, zunächst die Tabelle in eine CSV-Datei zu konvertieren. Nach dem Konvertieren der Tabelle können Sie Code schreiben, um die Datei in Befehle zum Erstellen von Zwillingen und Beziehungen zu übersetzen. Das folgende Codebeispiel veranschaulicht das Lesen der Daten aus der CSV-Datei und das Erstellen eines Zwillingsgraphen in Azure Digital Twins.

Im folgenden Code weist die CSV-Datei den Namen data.csv auf, und es gibt einen Platzhalter, der für den Hostnamen Ihrer Azure Digital Twins-Instanz steht. Das Beispiel nutzt auch mehrere Pakete, die Sie dem Projekt zur Unterstützung dieses Prozesses hinzufügen können.

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

namespace creating_twin_graph_from_csv
{
    class Program
    {
        static async Task Main(string[] args)
        {
            var relationshipRecordList = new List<BasicRelationship>();
            var twinList = new List<BasicDigitalTwin>();
            List<List<string>> data = ReadData();
            DigitalTwinsClient client = CreateDtClient();

            // Interpret the CSV file data, by each row
            foreach (List<string> row in data)
            {
                string modelID = row.Count > 0 ? row[0].Trim() : null;
                string srcID = row.Count > 1 ? row[1].Trim() : null;
                string relName = row.Count > 2 ? row[2].Trim() : null;
                string targetID = row.Count > 3 ? row[3].Trim() : null;
                string initProperties = row.Count > 4 ? row[4].Trim() : null;
                Console.WriteLine($"ModelID: {modelID}, TwinID: {srcID}, RelName: {relName}, TargetID: {targetID}, InitData: {initProperties}");
                var props = new Dictionary<string, object>();
                // Parse properties into dictionary (left out for compactness)
                // ...

                // Null check for source and target IDs
                if (!string.IsNullOrWhiteSpace(srcID) && !string.IsNullOrWhiteSpace(targetID) && !string.IsNullOrWhiteSpace(relName))
                {
                    relationshipRecordList.Add(
                        new BasicRelationship
                        {
                            SourceId = srcID,
                            TargetId = targetID,
                            Name = relName,
                        });
                }

                if (!string.IsNullOrWhiteSpace(srcID) && !string.IsNullOrWhiteSpace(modelID))
                twinList.Add(
                    new BasicDigitalTwin
                    {
                        Id = srcID,
                        Metadata = { ModelId = modelID },
                        Contents = props,
                    });
            }

            // Create digital twins
            foreach (BasicDigitalTwin twin in twinList)
            {
                try
                {
                    await client.CreateOrReplaceDigitalTwinAsync<BasicDigitalTwin>(twin.Id, twin);
                    Console.WriteLine("Twin is created");
                }
                catch (RequestFailedException ex)
                {
                    Console.WriteLine($"Error {ex.Status}: {ex.Message}");
                }
            }

            // Create relationships between the twins
            foreach (BasicRelationship rec in relationshipRecordList)
            {
                string relId = $"{rec.SourceId}-{rec.Name}->{rec.TargetId}";
                try
                {
                    await client.CreateOrReplaceRelationshipAsync<BasicRelationship>(rec.SourceId, relId, rec);
                    Console.WriteLine($"Relationship {relId} is created");
                }
                catch (RequestFailedException ex)
                {
                    Console.WriteLine($"Error creating relationship {relId}. {ex.Status}: {ex.Message}");
                }
            }
        }

        // Method to ingest data from the CSV file
        public static List<List<string>> ReadData()
        {
            string path = "<path-to>/data.csv";
            string[] lines = System.IO.File.ReadAllLines(path);
            var data = new List<List<string>>();
            int count = 0;
            foreach (string line in lines)
            {
                if (count++ == 0)
                    continue;
                var cols = new List<string>();
                string[] columns = line.Split(',');
                foreach (string column in columns)
                {
                    cols.Add(column);
                }
                data.Add(cols);
            }
            return data;
        }

        // Method to create the digital twins client
        private static DigitalTwinsClient CreateDtClient()
        {
            string adtInstanceUrl = "https://<your-instance-hostname>";
            var credentials = new DefaultAzureCredential();
            return new DigitalTwinsClient(new Uri(adtInstanceUrl), credentials);
        }
    }
}

Ausführbares Zwillingsgraphenbeispiel

Der folgende ausführbare Codeausschnitt verwendet die Beziehungsvorgänge aus diesem Artikel, um einen Zwillingsgraphen aus digitalen Zwillingen und Beziehungen zu erstellen.

Einrichten von Beispielprojektdateien

Der Codeausschnitt verwendet zwei Beispielmodelldefinitionen: Room.json und Floor.json. Um die Modelldateien herunterladen und in Ihrem Code verwenden zu können, verwenden Sie diese Links für die direkte Navigation zu den Dateien in GitHub. Klicken Sie dann mit der rechten Maustaste auf eine beliebige Stelle auf dem Bildschirm, wählen Sie im Kontextmenü Ihres Browsers Speichern unter aus, und verwenden Sie das Fenster „Speichern unter“, um die Dateien als Room.json und Floor.json zu speichern.

Erstellen Sie als Nächstes ein neues Konsolen-App-Projekt in Visual Studio oder einem Editor Ihrer Wahl.

Kopieren Sie dann den folgenden Code des ausführbaren Beispiels in Ihr Projekt:

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

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

            // Create the Azure Digital Twins client for API calls
            DigitalTwinsClient client = createDtClient();
            Console.WriteLine($"Service client created – ready to go");
            Console.WriteLine();

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

            // Create new (Floor) digital twin
            var floorTwin = new BasicDigitalTwin();
            string srcId = "myFloorID";
            floorTwin.Metadata.ModelId = "dtmi:example:Floor;1";
            // Floor twins have no properties, so nothing to initialize
            // Create the twin
            await client.CreateOrReplaceDigitalTwinAsync<BasicDigitalTwin>(srcId, floorTwin);
            Console.WriteLine("Twin created successfully");

            // Create second (Room) digital twin
            var roomTwin = new BasicDigitalTwin();
            string targetId = "myRoomID";
            roomTwin.Metadata.ModelId = "dtmi:example:Room;1";
            // Initialize properties
            roomTwin.Contents.Add("Temperature", 35.0);
            roomTwin.Contents.Add("Humidity", 55.0);
            // Create the twin
            await client.CreateOrReplaceDigitalTwinAsync<BasicDigitalTwin>(targetId, roomTwin);
            
            // Create relationship between them
            var properties = new Dictionary<string, object>
            {
                { "ownershipUser", "ownershipUser original value" },
            };
            // <UseCreateRelationship>
            await CustomMethod_CreateRelationshipAsync(client, srcId, targetId, "contains", properties);
            // </UseCreateRelationship>
            Console.WriteLine();

            // Update relationship's Name property
            // <UseUpdateRelationship>
            var updatePropertyPatch = new JsonPatchDocument();
            updatePropertyPatch.AppendAdd("/ownershipUser", "ownershipUser NEW value");
            await CustomMethod_UpdateRelationshipAsync(client, srcId, $"{srcId}-contains->{targetId}", updatePropertyPatch);
            // </UseUpdateRelationship>
            Console.WriteLine();

            //Print twins and their relationships
            Console.WriteLine("--- Printing details:");
            Console.WriteLine($"Outgoing relationships from source twin, {srcId}:");
            // <UseFetchAndPrint>
            await CustomMethod_FetchAndPrintTwinAsync(srcId, client);
            // </UseFetchAndPrint>
            Console.WriteLine();
            Console.WriteLine($"Incoming relationships to target twin, {targetId}:");
            await CustomMethod_FetchAndPrintTwinAsync(targetId, client);
            Console.WriteLine("--------");
            Console.WriteLine();

            // Delete the relationship
            // <UseDeleteRelationship>
            await CustomMethod_DeleteRelationshipAsync(client, srcId, $"{srcId}-contains->{targetId}");
            // </UseDeleteRelationship>
            Console.WriteLine();

            // Print twins and their relationships again
            Console.WriteLine("--- Printing details (after relationship deletion):");
            Console.WriteLine("Outgoing relationships from source twin:");
            await CustomMethod_FetchAndPrintTwinAsync(srcId, client);
            Console.WriteLine();
            Console.WriteLine("Incoming relationships to target twin:");
            await CustomMethod_FetchAndPrintTwinAsync(targetId, client);
            Console.WriteLine("--------");
            Console.WriteLine();
        }

        private static DigitalTwinsClient createDtClient()
        {
            string adtInstanceUrl = "https://<your-instance-hostname>";
            var credentials = new DefaultAzureCredential();
            var client = new DigitalTwinsClient(new Uri(adtInstanceUrl), credentials);
            return client;
        }

        // <CreateRelationshipMethod>
        private async static Task CustomMethod_CreateRelationshipAsync(DigitalTwinsClient client, string srcId, string targetId, string relName, IDictionary<string,object> inputProperties)
        {
            var relationship = new BasicRelationship
            {
                TargetId = targetId,
                Name = relName,
                Properties = inputProperties
            };

            try
            {
                string relId = $"{srcId}-{relName}->{targetId}";
                await client.CreateOrReplaceRelationshipAsync<BasicRelationship>(srcId, relId, relationship);
                Console.WriteLine($"Created {relName} relationship successfully. Relationship ID is {relId}.");
            }
            catch (RequestFailedException rex)
            {
                Console.WriteLine($"Create relationship error: {rex.Status}:{rex.Message}");
            }

        }
        // </CreateRelationshipMethod>

        // <UpdateRelationshipMethod>
        private async static Task CustomMethod_UpdateRelationshipAsync(DigitalTwinsClient client, string srcId, string relId, Azure.JsonPatchDocument updateDocument)
        {

            try
            {
                await client.UpdateRelationshipAsync(srcId, relId, updateDocument);
                Console.WriteLine($"Successfully updated {relId}");
            }
            catch (RequestFailedException rex)
            {
                Console.WriteLine($"Update relationship error: {rex.Status}:{rex.Message}");
            }

        }
        // </UpdateRelationshipMethod>

        // <FetchAndPrintMethod>
        private static async Task CustomMethod_FetchAndPrintTwinAsync(string twin_Id, DigitalTwinsClient client)
        {
            Response<BasicDigitalTwin> res = await client.GetDigitalTwinAsync<BasicDigitalTwin>(twin_Id);
            // <UseFindOutgoingRelationships>
            await CustomMethod_FindOutgoingRelationshipsAsync(client, twin_Id);
            // </UseFindOutgoingRelationships>
            // <UseFindIncomingRelationships>
            await CustomMethod_FindIncomingRelationshipsAsync(client, twin_Id);
            // </UseFindIncomingRelationships>

            return;
        }
        // </FetchAndPrintMethod>

        // <FindOutgoingRelationshipsMethod>
        private static async Task<List<BasicRelationship>> CustomMethod_FindOutgoingRelationshipsAsync(DigitalTwinsClient client, string dtId)
        {
            // Find the relationships for the twin
            
            try
            {
                // GetRelationshipsAsync will throw if an error occurs
                // <GetRelationshipsCall>
                AsyncPageable<BasicRelationship> rels = client.GetRelationshipsAsync<BasicRelationship>(dtId);
                // </GetRelationshipsCall>
                var results = new List<BasicRelationship>();
                await foreach (BasicRelationship rel in rels)
                {
                    results.Add(rel);
                    Console.WriteLine($"Found relationship: {rel.Id}");

                    //Print its properties
                    Console.WriteLine($"Relationship properties:");
                    foreach(KeyValuePair<string, object> property in rel.Properties)
                    {
                        Console.WriteLine("{0} = {1}", property.Key, property.Value);
                    }
                }

                return results;
            }
            catch (RequestFailedException ex)
            {
                Console.WriteLine($"*** Error {ex.Status}/{ex.ErrorCode} retrieving relationships for {dtId} due to {ex.Message}");
                return null;
            }
        }
        // </FindOutgoingRelationshipsMethod>

        // <FindIncomingRelationshipsMethod>
        private static async Task<List<IncomingRelationship>> CustomMethod_FindIncomingRelationshipsAsync(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);

                var results = new List<IncomingRelationship>();
                await foreach (IncomingRelationship incomingRel in incomingRels)
                {
                    results.Add(incomingRel);
                    Console.WriteLine($"Found incoming relationship: {incomingRel.RelationshipId}");

                    //Print its properties
                    Response<BasicRelationship> relResponse = await client.GetRelationshipAsync<BasicRelationship>(incomingRel.SourceId, incomingRel.RelationshipId);
                    BasicRelationship rel = relResponse.Value;
                    Console.WriteLine($"Relationship properties:");
                    foreach(KeyValuePair<string, object> property in rel.Properties)
                    {
                        Console.WriteLine("{0} = {1}", property.Key, property.Value);
                    }
                }
                return results;
            }
            catch (RequestFailedException ex)
            {
                Console.WriteLine($"*** Error {ex.Status}/{ex.ErrorCode} retrieving incoming relationships for {dtId} due to {ex.Message}");
                return null;
            }
        }
        // </FindIncomingRelationshipsMethod>

        // <DeleteRelationshipMethod>
        private static async Task CustomMethod_DeleteRelationshipAsync(DigitalTwinsClient client, string srcId, string relId)
        {
            try
            {
                Response response = await client.DeleteRelationshipAsync(srcId, relId);
                await CustomMethod_FetchAndPrintTwinAsync(srcId, client);
                Console.WriteLine("Deleted relationship successfully");
            }
            catch (RequestFailedException e)
            {
                Console.WriteLine($"Error {e.ErrorCode}");
            }
        }
        // </DeleteRelationshipMethod>
    }
}

Hinweis

Es gibt derzeit ein bekanntes Problem, das die DefaultAzureCredential-Wrapperklasse betrifft und zu einem Fehler bei der Authentifizierung führen kann. Wenn dieses Problem auftritt, können Sie zum Beheben des Problems versuchen, DefaultAzureCredential mit dem folgenden optionalen Parameter zu instanziieren: new DefaultAzureCredential(new DefaultAzureCredentialOptions { ExcludeSharedTokenCacheCredential = true });

Weitere Informationen zu diesem Problem finden Sie unter Bekannte Probleme von Azure Digital Twins.

Projekt konfigurieren

Führen Sie als dann die folgenden Schritte aus, um den Projektcode zu konfigurieren:

  1. Fügen Sie Ihrem Projekt die Dateien Room.json und Floor.json hinzu, die Sie zuvor heruntergeladen haben, und ersetzen Sie die Platzhalter <path-to> im Code, um dem Programm mitzuteilen, wo sie zu finden sind.

  2. Ersetzen Sie den Platzhalter <your-instance-hostname> durch den Hostnamen Ihrer Azure Digital Twins-Instanz.

  3. Als Nächstes fügen Sie Ihrem Projekt zwei Abhängigkeiten hinzu, die erforderlich sind, um Azure Digital Twins verwenden zu können. Bei der ersten handelt es sich um das Paket für das Azure Digital Twins SDK für .NET, und die zweite stellt Tools zur Unterstützung der Authentifizierung bei Azure bereit.

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

Sie müssen auch lokale Anmeldeinformationen einrichten, wenn Sie das Beispiel direkt ausführen möchten. Im nächsten Abschnitt wird dieser Prozess erläutert.

Einrichten lokaler Azure-Anmeldeinformationen

Dieses Beispiel verwendet DefaultAzureCredential (Teil der Azure.Identity-Bibliothek) zur Authentifizierung von Benutzern mit der Azure Digital Twins-Instanz, wenn Sie diese auf Ihrem lokalen Computer ausführen. Weitere Informationen zu den verschiedenen Möglichkeiten, wie sich eine Client-App bei Azure Digital Twins authentifizieren kann, finden Sie unter Schreiben von App-Authentifizierungscode.

Mit DefaultAzureCredential sucht das Beispiel nach Anmeldeinformationen in Ihrer lokalen Umgebung, wie eine Azure-Anmeldung in einer lokalen DefaultAzureCredential oder in Visual Studio oder Visual Studio Code. Aus diesem Grund sollten Sie sich lokal über einen dieser Mechanismen bei Azure anmelden, um Anmeldeinformationen für das Beispiel einzurichten.

Wenn Sie Visual Studio oder Visual Studio Code zum Ausführen von Codebeispielen verwenden, stellen Sie sicher, dass Sie bei diesem Editor mit denselben Anmeldeinformationen für Azure angemeldet sind, die Sie für den Zugriff auf Ihre Instanz von Azure Digital Twins verwenden möchten. Wenn Sie ein lokales CLI-Fenster verwenden, führen Sie den Befehl az login aus, um sich bei Ihrem Azure-Konto anzumelden. Wenn Sie danach Ihr Codebeispiel ausführen, sollten Sie automatisch authentifiziert werden.

Ausführen des Beispiels

Nachdem Sie das Setup abgeschlossen haben, können Sie das Beispielcodeprojekt ausführen.

Dies ist die Konsolenausgabe des Programms:

Screenshot of the console output showing the twin details with incoming and outgoing relationships of the twins.

Tipp

Der Zwillingsgraph ist ein Konzept zur Erstellung von Beziehungen zwischen Zwillingen. Wenn Sie sich die visuelle Darstellung des Zwillingsgraphen ansehen möchten, lesen Sie den Abschnitt Visualisierung dieses Artikels.

Nächste Schritte

Erfahren Sie mehr über die Abfrage eines Azure Digital Twins-Zwillingsgraphen: