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 bestaat uit afzonderlijke digitale dubbels die zijn verbonden via relaties. Dit artikel richt zich op het beheren van relaties en de grafiek als geheel; Als u wilt werken met afzonderlijke digitale dubbels, raadpleegt u Digitale dubbels beheren.
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 met Azure Digital Twins in dit artikel wilt werken, hebt u een Azure Digital Twins-exemplaar en de vereiste machtigingen nodig om deze 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 om te controleren of u elke stap hebt voltooid.
Nadat u uw exemplaar hebt ingesteld, noteert u de hostnaam van het exemplaar. U vindt de hostnaam in Azure Portal.
Ontwikkelaarsinterfaces
In dit artikel wordt uitgelegd hoe u verschillende beheerbewerkingen kunt uitvoeren met behulp van de .NET-SDK (C#). U kunt dezelfde beheeroproepen ook maken met behulp van de andere taal-SDK's 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 hulpmiddel 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, op te vragen en 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:
Relaties maken
Relaties beschrijven hoe verschillende digitale dubbels met elkaar zijn verbonden, die de basis vormen van de tweelinggrafiek.
De typen relaties die kunnen worden gemaakt van een (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 waar de relatie vandaan komt. - De doeldubbel-id (
targetId
in het onderstaande codevoorbeeld): de id van de dubbel waar de relatie binnenkomt. - Een relatienaam (
relName
in het onderstaande codevoorbeeld): het algemene type relatie, iets als bevat. - Een relatie-id (
relId
in het onderstaande codevoorbeeld): de specifieke naam voor deze relatie, bijvoorbeeld Relationship1.
De relatie-id moet uniek zijn binnen de opgegeven brondubbel. Het hoeft niet wereldwijd uniek te zijn. Voor de tweeling Foo moet elke specifieke relatie-id bijvoorbeeld uniek zijn. Een andere dubbelbalk 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. Deze maakt gebruik van de SDK-aanroep (gemarkeerd) binnen een aangepaste methode die kan worden 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 worden aangeroepen om een bevatrelatie te maken op de volgende manier:
await CustomMethod_CreateRelationshipAsync(client, srcId, targetId, "contains", properties);
Als u meerdere relaties wilt maken, kunt u aanroepen naar dezelfde methode herhalen en verschillende relatietypen doorgeven aan het argument.
Zie Azure Digital Twins-API's en SDK's voor meer informatie over de helperklasse.BasicRelationship
Meerdere relaties tussen dubbels 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 wijzen om een 'binnenkomende' koppeling te maken. De
GetIncomingRelationshipsAsync()
methode wordt gebruikt om binnenkomende relaties van een tweeling 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. Twin A kan bijvoorbeeld zowel een opgeslagen relatie als een gefabriceerde relatie hebben met Twin B.
U kunt zelfs meerdere exemplaren van hetzelfde type relatie maken tussen dezelfde twee tweelingen, als u wilt. In dit voorbeeld kan Tweeling A twee verschillende opgeslagen relaties hebben met Twin B, zolang de relaties 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.
Relaties bulksgewijs maken met de IMPORT Jobs-API
U kunt de IMPORT Jobs-API gebruiken om veel relaties tegelijk te maken in één API-aanroep. Deze methode vereist het gebruik van Azure Blob Storage, evenals schrijfmachtigingen in uw Azure Digital Twins-exemplaar voor relaties en bulktaken.
Tip
Met de IMPORT Jobs-API kunnen modellen en tweelingen ook in dezelfde aanroep worden geïmporteerd om alle onderdelen van een grafiek tegelijk te maken. Zie Modellen, tweelingen en relaties bulksgewijs uploaden met de Import Jobs-API voor meer informatie over dit proces.
Als u relaties bulksgewijs wilt importeren, moet u uw relaties (en alle andere resources die zijn opgenomen in de bulkimporttaak) structuren als een NDJSON-bestand . De Relationships
sectie komt na de Twins
sectie, waardoor deze de laatste grafiekgegevenssectie in het bestand is. Relaties die in het bestand zijn gedefinieerd, kunnen verwijzen naar dubbels die zijn gedefinieerd in dit bestand of die al aanwezig zijn in het exemplaar, en ze kunnen eventueel initialisatie opnemen van alle eigenschappen die de relaties hebben.
U kunt een voorbeeld van een importbestand en een voorbeeldproject bekijken voor het maken van deze bestanden in de inleiding tot de importtaken-API.
Vervolgens moet het bestand worden geüpload naar een toevoeg-blob in Azure Blob Storage. Zie Een container maken voor instructies over het maken van een Azure-opslagcontainer. Upload vervolgens het bestand met behulp van de uploadmethode van uw voorkeur (sommige opties zijn de AzCopy-opdracht, de Azure CLI of de Azure-portal).
Zodra het NDJSON-bestand is geüpload naar de container, haalt u de URL op in de blobcontainer. U gebruikt deze waarde verderop in de hoofdtekst van de API-aanroep voor bulkimport.
Hier volgt een schermopname van de URL-waarde van een blobbestand in Azure Portal:
Vervolgens kan het bestand worden gebruikt in een API-aanroep importtaken. U geeft de BLOB Storage-URL van het invoerbestand op, evenals een nieuwe BLOB Storage-URL om aan te geven waar u het uitvoerlogboek wilt opslaan wanneer het door de service wordt gemaakt.
Lijst met relaties
Eigenschappen van één relatie weergeven
U kunt relatiegegevens altijd deserialiseren naar een type van uw keuze. Gebruik het type BasicRelationship
voor basistoegang tot een relatie. 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. Deze maakt gebruik van de SDK-aanroep (gemarkeerd) binnen een aangepaste methode die kan worden 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 zien:
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 deze te gebruiken als id voor de 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 is 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) binnen een aangepaste methode gebruikt die kan worden 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 deze aangepaste methode nu aanroepen om de binnenkomende relaties van de tweelingen als volgt te zien:
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 dubbel 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 bedoeld 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 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 waarin wordt getoond hoe u deze methode gebruikt. In dit voorbeeld wordt de SDK-aanroep (gemarkeerd) binnen een aangepaste methode gebruikt die kan worden 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 naar 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
De eerste parameter geeft de brondubbel aan (de tweeling waar de relatie vandaan komt). 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 dubbel.
Hier ziet u voorbeeldcode die laat zien hoe u deze methode gebruikt. In dit voorbeeld wordt de SDK-aanroep (gemarkeerd) binnen een aangepaste methode gebruikt die kan worden 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 deze aangepaste methode nu aanroepen om een relatie als volgt te verwijderen:
await CustomMethod_DeleteRelationshipAsync(client, srcId, $"{srcId}-contains->{targetId}");
Notitie
Als u alle modellen, tweelingen en relaties in een exemplaar tegelijk wilt verwijderen, gebruikt u de API Taken verwijderen.
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, tweelingen en relaties te uploaden om ze één voor één te uploaden.
Modellen, tweelingen en relaties bulksgewijs uploaden met de API Import Jobs
U kunt de IMPORT Jobs-API gebruiken om meerdere modellen, dubbels en relaties met uw exemplaar te uploaden in één API-aanroep, waardoor de grafiek in één keer wordt gemaakt. Deze methode vereist het gebruik van Azure Blob Storage, evenals schrijfmachtigingen in uw Azure Digital Twins-exemplaar voor grafiekelementen (modellen, dubbels en relaties) en bulktaken.
Als u resources bulksgewijs wilt importeren, maakt u eerst een NDJSON-bestand met de details van uw resources. Het bestand begint met een Header
sectie, gevolgd door de optionele secties Models
, Twins
en Relationships
. U hoeft niet alle drie de typen grafiekgegevens in het bestand op te nemen, maar alle secties die aanwezig zijn, moeten deze volgorde volgen. Twins die in het bestand zijn gedefinieerd, kunnen verwijzen naar modellen die zijn gedefinieerd in dit bestand of die al aanwezig zijn in het exemplaar, en ze kunnen eventueel initialisatie van de eigenschappen van de dubbel bevatten. Relaties die in het bestand zijn gedefinieerd, kunnen verwijzen naar dubbels die zijn gedefinieerd in dit bestand of die al aanwezig zijn in het exemplaar, en ze kunnen eventueel initialisatie van relatie-eigenschappen bevatten.
U kunt een voorbeeld van een importbestand en een voorbeeldproject bekijken voor het maken van deze bestanden in de inleiding tot de importtaken-API.
Vervolgens moet het bestand worden geüpload naar een toevoeg-blob in Azure Blob Storage. Zie Een container maken voor instructies over het maken van een Azure-opslagcontainer. Upload vervolgens het bestand met behulp van de uploadmethode van uw voorkeur (sommige opties zijn de AzCopy-opdracht, de Azure CLI of de Azure-portal).
Zodra het NDJSON-bestand is geüpload naar de container, haalt u de URL op in de blobcontainer. U gebruikt deze waarde verderop in de hoofdtekst van de API-aanroep voor bulkimport.
Hier volgt een schermopname van de URL-waarde van een blobbestand in Azure Portal:
Vervolgens kan het bestand worden gebruikt in een API-aanroep importtaken. U geeft de BLOB Storage-URL van het invoerbestand op, evenals een nieuwe BLOB Storage-URL om aan te geven waar u het uitvoerlogboek wilt opslaan wanneer het door de service wordt gemaakt.
Grafiek importeren met Azure Digital Twins Explorer
Azure Digital Twins Explorer is een visueel hulpmiddel voor het weergeven en gebruiken van uw tweelinggrafiek. Het bevat een functie voor het importeren van een grafiekbestand in JSON- of Excel-indeling die meerdere modellen, tweelingen en relaties kan bevatten.
Zie De importgrafiek in de documentatie van Azure Digital Twins Explorer voor gedetailleerde informatie over het gebruik van deze functie.
Dubbels en relaties maken op basis van een CSV-bestand
Soms moet u mogelijk dubbelhiërarchieën maken op basis 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) | Naam van de relatie | Doeldubbel-id | Dubbele init-gegevens |
---|---|---|---|---|
dtmi:example:Floor; 1 | Floor1 | bevat | Kamer1 | |
dtmi:example:Floor; 1 | Floor0 | bevat | Room0 | |
dtmi:example:Room; 1 | Kamer1 | {"Temperatuur": 80} | ||
dtmi:example:Room; 1 | Room0 | {"Temperatuur": 70} |
Een manier om deze gegevens naar Azure Digital Twins te halen, 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 tweelingen en relaties te maken. Het volgende codevoorbeeld illustreert het lezen van de gegevens uit het CSV-bestand en het maken van een dubbelgrafiek in Azure Digital Twins.
In de onderstaande code wordt het CSV-bestand data.csv genoemd 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 met 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 runnable twin graph
In het volgende runnable 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 uw gewenste editor.
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 dat van invloed is op de DefaultAzureCredential
wrapper-klasse die 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:
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 moeten worden gevonden.Vervang de tijdelijke aanduiding
<your-instance-hostname>
door de hostnaam van uw Azure Digital Twins-exemplaar.Voeg twee afhankelijkheden toe aan uw project die nodig zijn om met Azure Digital Twins te werken. Het eerste is het pakket voor de Azure Digital Twins SDK voor .NET en de tweede biedt hulpprogramma's voor verificatie met 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. Daarna moet u, wanneer u het codevoorbeeld uitvoert, automatisch worden geverifieerd.
De voorbeeldtoepassing uitvoeren
Nu u de installatie hebt voltooid, kunt u het voorbeeldcodeproject uitvoeren.
Dit is de console-uitvoer van het programma:
Tip
De tweelinggrafiek is een concept van het maken van relaties tussen tweelingen. Als u de visuele weergave van de tweelinggrafiek wilt weergeven, raadpleegt u de sectie Visualisatie van dit artikel.
Volgende stappen
Meer informatie over het uitvoeren van query's op een Azure Digital Twins-tweelinggrafiek: