Een grafiek van digitale dubbels beheren met behulp van relaties

Het hart van Azure Digital Twins is de tweelinggrafiek die uw hele omgeving vertegenwoordigt. De tweelinggrafiek is gemaakt van afzonderlijke digitale dubbels die zijn verbonden via relaties. Dit artikel richt zich op het beheren van relaties en de grafiek als geheel; Zie Digitale dubbels beheren om met afzonderlijke digitale dubbels te werken.

Zodra u een werkende Azure Digital Twins-instantie hebt en verificatiecode hebt ingesteld in uw client-app, kunt u digitale dubbels en hun relaties maken, wijzigen en verwijderen in een Azure Digital Twins-exemplaar.

Vereisten

Als u in dit artikel met Azure Digital Twins wilt werken, hebt u een Azure Digital Twins-exemplaar en de vereiste machtigingen nodig om dit te gebruiken. Als u al een Azure Digital Twins-exemplaar hebt ingesteld, kunt u dat exemplaar gebruiken en doorgaan naar de volgende sectie.

Volg anders de instructies in Een instantie en verificatie instellen. De instructies bevatten informatie waarmee u kunt controleren of u elke stap hebt voltooid.

Nadat u uw exemplaar hebt ingesteld, noteert u de volgende waarden. U hebt deze waarden later nodig om verbinding te maken met het exemplaar:

  • De hostnaam van het exemplaar. U vindt de hostnaam in de Azure Portal.
  • Het Azure-abonnement dat u hebt gebruikt om het exemplaar te maken. De naam of id werkt. U vindt het abonnement op de pagina Overzicht van uw exemplaar in de Azure Portal.

Ontwikkelaarsinterfaces

In dit artikel wordt beschreven hoe u verschillende beheerbewerkingen uitvoert met behulp van de .NET -SDK (C#). U kunt dezelfde beheeroproepen ook maken met behulp van de SDK's voor andere talen die worden beschreven in Azure Digital Twins API's en SDK's.

Andere ontwikkelaarsinterfaces die kunnen worden gebruikt om deze bewerkingen te voltooien, zijn onder andere:

Visualisatie

Azure Digital Twins Explorer is een visueel hulpprogramma voor het verkennen van de gegevens in uw Azure Digital Twins-grafiek. U kunt de verkenner gebruiken om uw modellen, tweelingen en relaties weer te geven, er query's op uit te voeren en deze te bewerken.

Zie Azure Digital Twins Explorer voor meer informatie over het hulpprogramma Azure Digital Twins Explorer. Zie Azure Digital Twins Explorer gebruiken voor gedetailleerde stappen voor het gebruik van de functies.

De visualisatie ziet er als volgt uit:

Schermopname van Azure Digital Twins Explorer met voorbeeldmodellen en dubbels.

Relaties maken

Relaties beschrijven hoe verschillende digitale dubbels met elkaar zijn verbonden, wat de basis vormt van de tweelinggrafiek.

De typen relaties die kunnen worden gemaakt van de ene (bron)dubbel naar een andere (doel)dubbel, worden gedefinieerd als onderdeel van het DTDL-model van de brondubbel. U kunt een exemplaar van een relatie maken met behulp van de CreateOrReplaceRelationshipAsync() SDK-aanroep met tweelingen en relatiedetails die volgen op de DTDL-definitie.

Als u een relatie wilt maken, moet u het volgende opgeven:

  • De brondubbel-id (srcId in het onderstaande codevoorbeeld): de id van de tweeling waarvan de relatie afkomstig is.
  • De doeldubbel-id (targetId in het onderstaande codevoorbeeld): de id van de tweeling waar de relatie binnenkomt.
  • Een relatienaam (relName in het onderstaande codevoorbeeld): het algemene type relatie, ongeveer als contains.
  • Een relatie-id (relId in het onderstaande codevoorbeeld): de specifieke naam voor deze relatie, bijvoorbeeld Relatie1.

De relatie-id moet uniek zijn binnen de opgegeven brondubbel. Het hoeft niet wereldwijd uniek te zijn. Voor de dubbel Foo moet bijvoorbeeld elke specifieke relatie-id uniek zijn. Een andere dubbele balk kan echter een uitgaande relatie hebben die overeenkomt met dezelfde id van een Foo-relatie.

In het volgende codevoorbeeld ziet u hoe u een relatie maakt in uw Azure Digital Twins-exemplaar. Er wordt gebruikgemaakt van de SDK-aanroep (gemarkeerd) in een aangepaste methode die mogelijk wordt weergegeven in de context van een groter programma.

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

}

Deze aangepaste functie kan nu op de volgende manier worden aangeroepen om een contains-relatie te maken:

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

Als u meerdere relaties wilt maken, kunt u aanroepen naar dezelfde methode herhalen, waarbij verschillende relatietypen worden doorgegeven aan het argument.

Zie Azure Digital Twins API's en SDK's voor meer informatie over de helperklasseBasicRelationship.

Meerdere relaties tussen tweelingen maken

Relaties kunnen worden geclassificeerd als:

  • Uitgaande relaties: relaties die behoren tot deze tweeling die naar buiten wijzen om deze te verbinden met andere tweelingen. De GetRelationshipsAsync() methode wordt gebruikt om uitgaande relaties van een tweeling op te halen.
  • Binnenkomende relaties: relaties die behoren tot andere tweelingen die naar deze dubbel verwijzen om een 'binnenkomende' koppeling te maken. De GetIncomingRelationshipsAsync() methode wordt gebruikt om binnenkomende relaties van een dubbel op te halen.

Er is geen beperking voor het aantal relaties dat u tussen twee tweelingen kunt hebben: u kunt zoveel relaties tussen tweelingen hebben als u wilt.

Dit betekent dat u verschillende soorten relaties tussen twee tweelingen tegelijk kunt uitdrukken. Dubbel A kan bijvoorbeeld zowel een opgeslagen relatie als een gefabriceerde relatie hebben met Dubbel B.

U kunt zelfs meerdere exemplaren van hetzelfde type relatie tussen dezelfde twee tweelingen maken, als u wilt. In dit voorbeeld kan Dubbel A twee verschillende opgeslagen relaties hebben met Dubbel B, zolang de relaties maar verschillende relatie-id's hebben.

Notitie

De DTDL-kenmerken van minMultiplicity en maxMultiplicity voor relaties worden momenteel niet ondersteund in Azure Digital Twins, zelfs als ze zijn gedefinieerd als onderdeel van een model, worden ze niet afgedwongen door de service. Zie Servicespecifieke DTDL-notities voor meer informatie.

Lijst met relaties

Eigenschappen van één relatie weergeven

U kunt relatiegegevens altijd deserialiseren naar een type van uw keuze. Gebruik voor basistoegang tot een relatie het type BasicRelationship. De BasicRelationship helperklasse biedt u ook toegang tot eigenschappen die zijn gedefinieerd voor de relatie, via een IDictionary<string, object>. Als u eigenschappen wilt weergeven, kunt u het volgende gebruiken:

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

Uitgaande relaties van een digitale dubbel weergeven

Als u toegang wilt krijgen tot de lijst met uitgaande relaties voor een bepaalde dubbel in de grafiek, kunt u de GetRelationships() methode als volgt gebruiken:

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

Deze methode retourneert een Azure.Pageable<T> of Azure.AsyncPageable<T>, afhankelijk van of u de synchrone of asynchrone versie van de aanroep gebruikt.

Hier volgt een voorbeeld waarmee een lijst met relaties wordt opgehaald. Er wordt gebruikgemaakt van de SDK-aanroep (gemarkeerd) in een aangepaste methode die mogelijk wordt weergegeven in de context van een groter programma.

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

U kunt deze aangepaste methode nu aanroepen om de uitgaande relaties van de tweelingen als volgt te bekijken:

await CustomMethod_FindOutgoingRelationshipsAsync(client, twin_Id);

U kunt de opgehaalde relaties gebruiken om naar andere tweelingen in uw grafiek te navigeren door het target veld te lezen uit de relatie die wordt geretourneerd en dit te gebruiken als de id voor uw volgende aanroep naar GetDigitalTwin().

Binnenkomende relaties met een digitale dubbel weergeven

Azure Digital Twins heeft ook een SDK-aanroep om alle binnenkomende relaties met een bepaalde dubbel te vinden. Deze SDK is vaak handig voor omgekeerde navigatie of bij het verwijderen van een dubbel.

Notitie

IncomingRelationship aanroepen retourneren niet de volledige hoofdtekst van de relatie. Zie de referentiedocumentatie voor meer informatie over de IncomingRelationship klasse.

Het codevoorbeeld in de vorige sectie was gericht op het vinden van uitgaande relaties van een dubbel. Het volgende voorbeeld is op dezelfde manier gestructureerd, maar zoekt in plaats daarvan binnenkomende relaties met de dubbel. In dit voorbeeld wordt ook de SDK-aanroep (gemarkeerd) gebruikt in een aangepaste methode die mogelijk wordt weergegeven in de context van een groter programma.

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

U kunt nu deze aangepaste methode aanroepen om de binnenkomende relaties van de tweelingen als volgt te bekijken:

await CustomMethod_FindIncomingRelationshipsAsync(client, twin_Id);

Alle eigenschappen en relaties van dubbels weergeven

Met behulp van de bovenstaande methoden voor het weergeven van uitgaande en binnenkomende relaties met een tweeling, kunt u een methode maken waarmee volledige dubbelgegevens worden afgedrukt, inclusief de eigenschappen van de dubbel en beide typen relaties. Hier volgt een voorbeeld van een aangepaste methode die laat zien hoe u de bovenstaande aangepaste methoden voor dit doel kunt combineren.

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

U kunt deze aangepaste functie nu als volgt aanroepen:

await CustomMethod_FetchAndPrintTwinAsync(srcId, client);

Relaties bijwerken

Relaties worden bijgewerkt met behulp van de UpdateRelationship -methode.

Notitie

Deze methode is voor het bijwerken van de eigenschappen van een relatie. Als u de brondubbel of doeldubbel van de relatie wilt wijzigen, moet u de relatie verwijderen en er een opnieuw maken met behulp van de nieuwe dubbels.

De vereiste parameters voor de clientoproep zijn:

  • De id van de brondubbel (de tweeling waar de relatie vandaan komt).
  • De id van de relatie die moet worden bijgewerkt.
  • Een JSON Patch-document met de eigenschappen en nieuwe waarden die u wilt bijwerken.

Hier volgt een voorbeeldcodefragment dat laat zien hoe u deze methode gebruikt. In dit voorbeeld wordt de SDK-aanroep (gemarkeerd) gebruikt in een aangepaste methode die mogelijk wordt weergegeven in de context van een groter programma.

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

}

Hier volgt een voorbeeld van een aanroep van deze aangepaste methode, waarbij een JSON Patch-document wordt doorgegeven met de informatie voor het bijwerken van een eigenschap.

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

Relaties verwijderen

Met de eerste parameter wordt de brondubbel opgegeven (de dubbel waaruit de relatie afkomstig is). De andere parameter is de relatie-id. U hebt zowel de dubbel-id als de relatie-id nodig, omdat relatie-id's alleen uniek zijn binnen het bereik van een tweeling.

Hier volgt een voorbeeldcode die laat zien hoe u deze methode gebruikt. In dit voorbeeld wordt de SDK-aanroep (gemarkeerd) gebruikt in een aangepaste methode die mogelijk wordt weergegeven in de context van een groter programma.

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

U kunt nu deze aangepaste methode aanroepen om een relatie als deze te verwijderen:

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

Meerdere grafiekelementen tegelijk maken

In deze sectie worden strategieën beschreven voor het maken van een grafiek met meerdere elementen tegelijk, in plaats van afzonderlijke API-aanroepen te gebruiken om modellen, dubbels en relaties te uploaden om ze één voor één te uploaden.

Grafiek importeren met Azure Digital Twins Explorer

Azure Digital Twins Explorer is een visueel hulpprogramma voor het weergeven van en interactie met uw tweelinggrafiek. Het bevat een functie voor het importeren van een grafiekbestand in JSON- of Excel-indeling die meerdere modellen, dubbels en relaties kan bevatten.

Zie Grafiek importeren in de documentatie van Azure Digital Twins Explorer voor gedetailleerde informatie over het gebruik van deze functie.

Dubbels en relaties maken vanuit een CSV-bestand

Soms moet u mogelijk dubbelhiërarchieën maken van gegevens die zijn opgeslagen in een andere database, of in een spreadsheet of een CSV-bestand. In deze sectie ziet u hoe u gegevens uit een CSV-bestand kunt lezen en er een dubbelgrafiek van kunt maken.

Bekijk de volgende gegevenstabel, waarin een set digitale dubbels en relaties wordt beschreven. De modellen waarnaar in dit bestand wordt verwezen, moeten al bestaan in het Azure Digital Twins-exemplaar.

Model-id Dubbel-id (moet uniek zijn) Relatienaam Doeldubbel-id Dubbele init-gegevens
dtmi:example:Floor;1 Floor1 bevat Kamer1
dtmi:example:Floor;1 Floor0 bevat Kamer0
dtmi:example:Room;1 Kamer1 {"Temperatuur": 80}
dtmi:example:Room;1 Kamer0 {"Temperatuur": 70}

Een manier om deze gegevens in Azure Digital Twins te krijgen, is door de tabel te converteren naar een CSV-bestand. Zodra de tabel is geconverteerd, kan code worden geschreven om het bestand te interpreteren in opdrachten om dubbels en relaties te maken. Het volgende codevoorbeeld illustreert het lezen van de gegevens uit het CSV-bestand en het maken van een tweelinggrafiek in Azure Digital Twins.

In de onderstaande code wordt het CSV-bestand data.csvgenoemd en is er een tijdelijke aanduiding die de hostnaam van uw Azure Digital Twins-exemplaar vertegenwoordigt. Het voorbeeld maakt ook gebruik van verschillende pakketten die u aan uw project kunt toevoegen om u te helpen bij dit proces.

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

Voorbeeld van uitvoerbare dubbelgrafiek

In het volgende uit te voeren codefragment worden de relatiebewerkingen uit dit artikel gebruikt om een dubbelgrafiek te maken van digitale dubbels en relaties.

Voorbeeldprojectbestanden instellen

Het codefragment maakt gebruik van twee voorbeeldmodeldefinities, Room.json en Floor.json. Als u de modelbestanden wilt downloaden zodat u ze in uw code kunt gebruiken, gebruikt u deze koppelingen om rechtstreeks naar de bestanden in GitHub te gaan. Klik vervolgens met de rechtermuisknop op een willekeurige plaats op het scherm, selecteer Opslaan als in het snelmenu van uw browser en gebruik het venster Opslaan als om de bestanden op te slaan als Room.json en Floor.json.

Maak vervolgens een nieuw console-app-project in Visual Studio of de editor van uw keuze.

Kopieer vervolgens de volgende code van het uitvoerbare voorbeeld naar uw project:

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

Notitie

Er is momenteel een bekend probleem met de DefaultAzureCredential wrapper-klasse dat kan leiden tot een fout tijdens het verifiëren. Als u dit probleem ondervindt, kunt u proberen te instantiëren DefaultAzureCredential met de volgende optionele parameter om dit op te lossen: new DefaultAzureCredential(new DefaultAzureCredentialOptions { ExcludeSharedTokenCacheCredential = true });

Zie Bekende problemen met Azure Digital Twins voor meer informatie over dit probleem.

Project configureren

Voer vervolgens de volgende stappen uit om uw projectcode te configureren:

  1. Voeg de Bestanden Room.json en Floor.json toe die u eerder hebt gedownload naar uw project en vervang de <path-to> tijdelijke aanduidingen in de code om uw programma te laten weten waar ze kunnen worden gevonden.

  2. Vervang de tijdelijke aanduiding <your-instance-hostname> door de hostnaam van uw Azure Digital Twins-exemplaar.

  3. Voeg twee afhankelijkheden toe aan uw project die nodig zijn om met Azure Digital Twins te werken. De eerste is het pakket voor de Azure Digital Twins SDK voor .NET en de tweede biedt hulpprogramma's voor verificatie bij Azure.

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

U moet ook lokale referenties instellen als u het voorbeeld rechtstreeks wilt uitvoeren. In de volgende sectie wordt dit proces beschreven.

Lokale Azure-referenties instellen

In dit voorbeeld wordt gebruikgemaakt van DefaultAzureCredential (onderdeel van de Azure.Identity-bibliotheek) om gebruikers te verifiëren bij de Azure Digital Twins-instantie wanneer u deze uitvoert op uw lokale machine. Voor meer informatie over verschillende manieren waarop een client-app kan verifiëren met Azure Digital Twins, raadpleegt u Verificatiecode voor app schrijven.

Met DefaultAzureCredential zoekt het voorbeeld naar referenties in uw lokale omgeving, zoals een Azure-aanmelding in een lokale Azure-CLI of in Visual Studio of Visual Studio Code. Daarom moet u zich lokaal aanmelden bij Azure via een van deze mechanismen om referenties in te stellen voor het voorbeeld.

Als u Visual Studio of Visual Studio Code gebruikt om codevoorbeelden uit te voeren, moet u ervoor zorgen dat u bent aangemeld bij die editor met dezelfde Azure-referenties die u wilt gebruiken voor toegang tot uw Azure Digital Twins-exemplaar. Als u een lokaal CLI-venster gebruikt, voert u de az login opdracht uit om u aan te melden bij uw Azure-account. Als u daarna uw codevoorbeeld uitvoert, wordt u automatisch geverifieerd.

De voorbeeldtoepassing uitvoeren

Nu u de installatie hebt voltooid, kunt u het voorbeeldcodeproject uitvoeren.

Dit is de console-uitvoer van het programma:

Schermopname van de console-uitvoer met de details van de tweeling met binnenkomende en uitgaande relaties van de tweelingen.

Tip

De tweelinggrafiek is een concept voor het maken van relaties tussen tweelingen. Als u de visuele weergave van de tweelinggrafiek wilt bekijken, raadpleegt u de sectie Visualisatie van dit artikel.

Volgende stappen

Meer informatie over het uitvoeren van query's op een Azure Digital Twins-tweelinggrafiek: