Digitális ikerpéldányok gráfjának kezelése kapcsolatok használatával

Az Azure Digital Twins középpontjában az egész környezetet képviselő ikergráf áll. Az ikergráf kapcsolatokon keresztül összekapcsolt egyedi digitális ikerpéldányokból áll. Ez a cikk a kapcsolatok és a gráf egészének kezelésével foglalkozik; az egyes digitális ikerpéldányok használatához lásd: Digitális ikerpéldányok kezelése.

Ha már rendelkezik egy működő Azure Digital Twins-példánysal , és beállította a hitelesítési kódot az ügyfélalkalmazásban, létrehozhat, módosíthat és törölhet digitális ikerpéldányokat és azok kapcsolatait egy Azure Digital Twins-példányban.

Előfeltételek

Az Azure Digital Twins ebben a cikkben való használatához szüksége lesz egy Azure Digital Twins-példányra és a használatához szükséges engedélyekre. Ha már beállított egy Azure Digital Twins-példányt, használhatja ezt a példányt, és ugorjon a következő szakaszra. Ellenkező esetben kövesse a példány és a hitelesítés beállítása című témakör utasításait. Az utasítások olyan információkat tartalmaznak, amelyek segítenek ellenőrizni, hogy sikeresen végrehajtotta-e az egyes lépéseket.

A példány beállítása után jegyezze fel a példány állomásnevét. A gazdagép nevét az Azure Portalon találja.

Fejlesztői felületek

Ez a cikk bemutatja, hogyan hajthat végre különböző felügyeleti műveleteket a .NET (C#) SDK használatával. Ugyanezeket a felügyeleti hívásokat az Azure Digital Twins API-kban és SDK-kban leírt egyéb nyelvi SDK-k használatával is létrehozhatja.

A műveletek végrehajtásához használható egyéb fejlesztői felületek a következők:

Visualization

Az Azure Digital Twins Explorer egy vizuális eszköz az Azure Digital Twins-gráf adatainak feltárására. Az Explorerrel megtekintheti, lekérdezheti és szerkesztheti modelljeit, ikerpéldányait és kapcsolatait.

Az Azure Digital Twins Explorer eszközről az Azure Digital Twins Explorerben olvashat. A funkciók használatának részletes lépéseit az Azure Digital Twins Explorer használata című témakörben találja.

Így néz ki a vizualizáció:

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

Kapcsolatok létrehozása

A kapcsolatok azt írják le, hogyan kapcsolódnak egymáshoz a különböző digitális ikerpéldányok, ami az ikergráf alapját képezi.

Az egyik (forrás)ikerpéldány és egy másik (cél) ikerpéldány között létrehozható kapcsolatok típusai a forrás ikerpéldány DTDL-modelljének részeként vannak definiálva. A kapcsolat egy példányát az Ikerpéldányokkal és a CreateOrReplaceRelationshipAsync() DTDL-definíciót követő kapcsolatadatokkal rendelkező SDK-hívással hozhatja létre.

Kapcsolat létrehozásához meg kell adnia a következőket:

  • A forrás ikerpéldány azonosítója (srcId az alábbi kódmintában): Annak az ikerpéldánynak az azonosítója, ahonnan a kapcsolat származik.
  • A cél ikerpéldány azonosítója (targetId az alábbi kódmintában): Annak az ikerpéldánynak az azonosítója, ahová a kapcsolat érkezik.
  • Egy kapcsolat neve (relNameaz alábbi kódmintában): A kapcsolat általános típusa, valami hasonló.
  • Kapcsolatazonosító (relId az alábbi kódmintában): A kapcsolat konkrét neve, valami hasonló : Kapcsolat1.

A kapcsolatazonosítónak egyedinek kell lennie a megadott forrás ikerpéldányon belül. Nem kell globálisan egyedinek lennie. Az ikerpéldány esetében például minden egyes kapcsolatazonosítónak egyedinek kell lennie. Egy másik ikersáv azonban olyan kimenő kapcsolatokkal rendelkezhet, amelyek megegyeznek a Foo-kapcsolat azonos azonosítójával.

Az alábbi kódminta bemutatja, hogyan hozhat létre kapcsolatot az Azure Digital Twins-példányban. Az SDK-hívást (kiemelve) egy egyéni metóduson belül használja, amely egy nagyobb program kontextusában jelenhet meg.

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

}

Ez az egyéni függvény mostantól meghívható, hogy a következő módon hozzon létre kapcsolatot:

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

Ha több kapcsolatot szeretne létrehozni, megismételheti a hívásokat ugyanahhoz a metódushoz, és különböző kapcsolattípusokat ad át az argumentumnak.

További információ a segédosztályról BasicRelationship: Azure Digital Twins API-k és SDK-k.

Több kapcsolat létrehozása ikerpéldányok között

A kapcsolatok az alábbiak szerint besorolhatók:

  • Kimenő kapcsolatok: Az ikerpéldányhoz tartozó kapcsolatok, amelyek kifelé mutatnak a többi ikerpéldányhoz való kapcsolódáshoz. A GetRelationshipsAsync() metódus egy ikerpéldány kimenő kapcsolatainak lekérésére szolgál.
  • Bejövő kapcsolatok: Más ikerpéldányokhoz tartozó kapcsolatok, amelyek erre az ikerpéldányra mutatnak, és létrehoznak egy "bejövő" hivatkozást. A GetIncomingRelationshipsAsync() metódus egy ikerpéldány bejövő kapcsolatainak lekérésére szolgál.

Nincs korlátozva a két ikerpéldány közötti kapcsolatok száma – az ikerpéldányok között tetszőleges számú kapcsolat lehet.

Ez a tény azt jelenti, hogy egyszerre több különböző típusú kapcsolatot is kifejezhet két ikerpéldány között. Az A ikerpéldány például tárolt és gyártott kapcsolatban is állhat a B ikerpéldánysal.

Akár több azonos típusú kapcsolatot is létrehozhat ugyanahhoz a két ikerpéldányhoz, ha szeretné. Ebben a példában az A ikerpéldánynak két különböző tárolt kapcsolata lehet a B ikerpéldánysal, feltéve, hogy a kapcsolatok különböző kapcsolatazonosítókkal rendelkeznek.

Megjegyzés:

A kapcsolatok DTDL-attribútumai minMultiplicity jelenleg maxMultiplicity nem támogatottak az Azure Digital Twinsben – még akkor sem, ha egy modell részeként vannak definiálva, a szolgáltatás nem fogja kikényszeríteni őket. További információ: Szolgáltatásspecifikus DTDL-megjegyzések.

Kapcsolatok tömeges létrehozása az Import Jobs API-val

Az Import Jobs API használatával egyszerre több kapcsolatot is létrehozhat egyetlen API-hívásban. Ez a módszer megköveteli az Azure Blob Storage használatát, valamint írási engedélyeket az Azure Digital Twins-példányban kapcsolatokhoz és tömeges feladatokhoz.

Tipp.

Az Importálási feladatok API lehetővé teszi a modellek és ikerpéldányok importálását ugyanabban a hívásban, hogy egyszerre hozza létre a gráf összes részét. Erről a folyamatról további információt a Modellek, ikerpéldányok és kapcsolatok tömeges feltöltése az Import Jobs API-val című témakörben talál.

A kapcsolatok tömeges importálásához NDJSON-fájlként kell strukturálnia a kapcsolatokat (és a tömeges importálási feladatban szereplő egyéb erőforrásokat). A Relationships szakasz a Twins szakasz után következik, így ez lesz a fájl utolsó gráfadatszakasza. A fájlban definiált kapcsolatok hivatkozhatnak az ebben a fájlban definiált vagy a példányban már meglévő ikerpéldányokra, és opcionálisan inicializálhatják a kapcsolatokkal rendelkező tulajdonságokat.

Az Importálási feladatok API bevezetőjében megtekintheti az importálási példafájlt és egy mintaprojektet, amellyel létrehozhatja ezeket a fájlokat.

Ezután a fájlt fel kell tölteni egy hozzáfűző blobba az Azure Blob Storage-ban. Az Azure Storage-tárolók létrehozásával kapcsolatos utasításokért lásd : Tároló létrehozása. Ezután töltse fel a fájlt az előnyben részesített feltöltési módszerrel (néhány lehetőség az AzCopy parancs, az Azure CLI vagy az Azure Portal).

Miután feltöltötte az NDJSON-fájlt a tárolóba, kérje le annak URL-címét a blobtárolóban. Ezt az értéket később fogja használni a tömeges importálási API-hívás törzsében.

Az alábbi képernyőképen egy blobfájl URL-értéke látható az Azure Portalon:

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

Ezután a fájl használható egy Importálási feladatok API-hívásban . Meg kell adnia a bemeneti fájl blobtároló URL-címét, valamint egy új blobtároló URL-címét, amely jelzi, hogy hol szeretné tárolni a kimeneti naplót a szolgáltatás létrehozásakor.

Kapcsolatok listázása

Egyetlen kapcsolat tulajdonságainak listázása

A kapcsolatadatokat mindig deszerializálhatja egy tetszőleges típusra. A kapcsolathoz való alapszintű hozzáféréshez használja a típust BasicRelationship. A BasicRelationship segédosztály a kapcsolaton definiált tulajdonságokhoz is hozzáférést biztosít egy IDictionary<string, object>. A tulajdonságok listázásához használhatja a következőt:

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

Egy digitális ikerpéldány kimenő kapcsolatainak listázása

Ha egy adott ikerpéldány kimenő kapcsolatainak listáját szeretné elérni a gráfban, az GetRelationships() alábbihoz hasonló módszert használhatja:

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

Ez a metódus egy Azure.Pageable<T> vagy Azure.AsyncPageable<T>, attól függően, hogy a hívás szinkron vagy aszinkron verzióját használja-e.

Íme egy példa, amely lekéri a kapcsolatok listáját. Az SDK-hívást (kiemelve) egy egyéni metóduson belül használja, amely egy nagyobb program kontextusában jelenhet meg.

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

Most már meghívhatja ezt az egyéni metódust az ikerpéldányok kimenő kapcsolatainak megtekintéséhez:

await CustomMethod_FindOutgoingRelationshipsAsync(client, twin_Id);

A lekért kapcsolatok segítségével a gráfban lévő többi ikerpéldányhoz is navigálhat, ha beolvassa a target visszaadott kapcsolat mezőit, és a következő hívás GetDigitalTwin()azonosítójaként használja.

Digitális ikerpéldány bejövő kapcsolatainak listázása

Az Azure Digital Twins SDK-hívással is rendelkezik, amely megkeresi az adott ikerpéldányhoz érkező összes bejövő kapcsolatot. Ez az SDK gyakran hasznos a fordított navigációhoz, vagy ikerpéldány törlésekor.

Megjegyzés:

IncomingRelationship a hívások nem a kapcsolat teljes törzsét adják vissza. Az osztályról további információt a IncomingRelationship referenciadokumentációban talál.

Az előző szakaszban szereplő kódminta az ikerpéldány kimenő kapcsolatainak megkeresésére összpontosított. Az alábbi példa hasonlóan strukturált, de ehelyett az ikerpéldányhoz kapcsolódó bejövő kapcsolatokat keresi. Ez a példa az SDK-hívást is használja (kiemelve) egy egyéni metóduson belül, amely egy nagyobb program kontextusában jelenhet meg.

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

Most már meghívhatja ezt az egyéni metódust az ikerpéldányok bejövő kapcsolatainak megtekintéséhez:

await CustomMethod_FindIncomingRelationshipsAsync(client, twin_Id);

Az összes ikertulajdonság és kapcsolat listázása

A fenti módszerekkel felsorolhatja az ikerpéldány kimenő és bejövő kapcsolatait, létrehozhat egy olyan metódust, amely teljes ikeradatokat nyomtat ki, beleértve az iker tulajdonságait és a kapcsolatok mindkét típusát. Íme egy egyéni példametódus, amely bemutatja, hogyan kombinálhatja a fenti egyéni metódusokat erre a célra.

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

Ezt az egyéni függvényt most a következőképpen hívhatja meg:

await CustomMethod_FetchAndPrintTwinAsync(srcId, client);

Kapcsolatok frissítése

A kapcsolatok a metódus használatával UpdateRelationship frissülnek.

Megjegyzés:

Ez a módszer egy kapcsolat tulajdonságainak frissítésére használható. Ha módosítania kell a kapcsolat forrás ikerpéldányát vagy cél ikerpéldányát, törölnie kell a kapcsolatot, és újra létre kell hoznia egyet az új ikerpéldányok használatával.

Az ügyfélhíváshoz szükséges paraméterek a következők:

  • A forrás ikerpéldány azonosítója (az ikerpéldány, ahonnan a kapcsolat származik).
  • A frissíteni kívánt kapcsolat azonosítója.
  • JSON Patch-dokumentum , amely tartalmazza a frissíteni kívánt tulajdonságokat és új értékeket.

Íme egy mintakódrészlet, amely bemutatja, hogyan használható ez a módszer. Ez a példa az SDK-hívást (kiemelve) használja egy egyéni metóduson belül, amely egy nagyobb program kontextusában jelenhet meg.

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

}

Íme egy példa erre az egyéni metódusra, amely egy JSON Patch-dokumentumot ad át a tulajdonság frissítéséhez szükséges információkkal.

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

Kapcsolatok törlése

Az első paraméter megadja a forrás ikerpéldányt (azt az ikerpéldányt, ahonnan a kapcsolat származik). A másik paraméter a kapcsolat azonosítója. Az ikerpéldány-azonosítóra és a kapcsolatazonosítóra is szüksége van, mivel a kapcsolatazonosítók csak az ikerpéldány hatókörén belül egyediek.

Az alábbi mintakód bemutatja, hogyan használható ez a módszer. Ez a példa az SDK-hívást (kiemelve) használja egy egyéni metóduson belül, amely egy nagyobb program kontextusában jelenhet meg.

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

Most már meghívhatja ezt az egyéni metódust egy ilyen kapcsolat törléséhez:

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

Megjegyzés:

Ha egyszerre szeretné törölni az összes modellt, ikerpéldányt és kapcsolatot egy példányban, használja a Feladatok törlése API-t.

Több gráfelem létrehozása egyszerre

Ez a szakasz azt ismerteti, hogyan hozhat létre egyszerre több elemet tartalmazó gráfot, és nem használhatja az egyes API-hívásokat modellek, ikerpéldányok és kapcsolatok feltöltésére egyesével.

Modellek, ikerpéldányok és kapcsolatok tömeges feltöltése az Import Jobs API-val

A Feladatok importálása API-val több modellt, ikerpéldányt és kapcsolatot tölthet fel a példányra egyetlen API-hívásban, így egyszerre hatékonyan hozhatja létre a gráfot. Ez a módszer megköveteli az Azure Blob Storage használatát, valamint írási engedélyeket az Azure Digital Twins-példányban gráfelemekhez (modellekhez, ikerpéldányokhoz és kapcsolatokhoz) és tömeges feladatokhoz.

Az erőforrások tömeges importálásához először hozzon létre egy NDJSON-fájlt , amely tartalmazza az erőforrások részleteit. A fájl egy Header szakaszsal kezdődik, majd a választható szakaszokModelsTwins, majd Relationshipsa . Nem kell mindhárom gráfadatot belefoglalnia a fájlba, de a jelen lévő szakaszoknak ezt a sorrendet kell követniük. A fájlban definiált ikerpéldányok hivatkozhatnak a fájlban definiált vagy a példányban már meglévő modellekre, és opcionálisan magukban foglalhatják az iker tulajdonságainak inicializálását is. A fájlban definiált kapcsolatok hivatkozhatnak az ebben a fájlban definiált vagy a példányban már meglévő ikerpéldányokra, és opcionálisan a kapcsolattulajdonságok inicializálását is magukban foglalhatják.

Az Importálási feladatok API bevezetőjében megtekintheti az importálási példafájlt és egy mintaprojektet, amellyel létrehozhatja ezeket a fájlokat.

Ezután a fájlt fel kell tölteni egy hozzáfűző blobba az Azure Blob Storage-ban. Az Azure Storage-tárolók létrehozásával kapcsolatos utasításokért lásd : Tároló létrehozása. Ezután töltse fel a fájlt az előnyben részesített feltöltési módszerrel (néhány lehetőség az AzCopy parancs, az Azure CLI vagy az Azure Portal).

Miután feltöltötte az NDJSON-fájlt a tárolóba, kérje le annak URL-címét a blobtárolóban. Ezt az értéket később fogja használni a tömeges importálási API-hívás törzsében.

Az alábbi képernyőképen egy blobfájl URL-értéke látható az Azure Portalon:

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

Ezután a fájl használható egy Importálási feladatok API-hívásban . Meg kell adnia a bemeneti fájl blobtároló URL-címét, valamint egy új blobtároló URL-címét, amely jelzi, hogy hol szeretné tárolni a kimeneti naplót a szolgáltatás létrehozásakor.

Gráf importálása az Azure Digital Twins Explorerrel

Az Azure Digital Twins Explorer egy vizuális eszköz az ikergráf megtekintésére és kezelésére. Egy JSON vagy Excel formátumú gráffájl importálására szolgáló funkciót tartalmaz, amely több modellt, ikerpéldányt és kapcsolatot tartalmazhat.

A funkció használatával kapcsolatos részletes információkért tekintse meg az Importálás gráfot az Azure Digital Twins Explorer dokumentációjában.

Ikerpéldányok és kapcsolatok létrehozása CSV-fájlból

Előfordulhat, hogy egy másik adatbázisban, számolótáblában vagy CSV-fájlban tárolt adatokból ikerhierarchiákat kell létrehoznia. Ez a szakasz bemutatja, hogyan olvashatja be az adatokat egy CSV-fájlból, és hogyan hozhat létre belőle ikergráfot.

Vegye figyelembe a következő adattáblát, amely a digitális ikerpéldányok és kapcsolatok készletét írja le. A fájlban hivatkozott modelleknek már létezniük kell az Azure Digital Twins-példányban.

Modellazonosító Ikerazonosító (egyedinek kell lennie) Kapcsolat neve Cél ikerpéldány azonosítója Iker inicializálási adatok
dtmi:example:Floor; 1 Emelet1 contains Szoba1
dtmi:example:Floor; 1 Emelet0 contains Szoba0
dtmi:example:Room; 1 Szoba1 {"Temperature": 80}
dtmi:example:Room; 1 Szoba0 {"Temperature": 70}

Az adatok Azure Digital Twinsbe való beolvasásának egyik módja, ha a táblát CSV-fájllá konvertálja. A táblázat konvertálása után kód írható a fájl parancsokká való értelmezéséhez ikerpéldányok és kapcsolatok létrehozásához. Az alábbi kódminta bemutatja a CSV-fájlból származó adatok beolvasását és egy ikergráf létrehozását az Azure Digital Twinsben.

Az alábbi kódban a CSV-fájlt data.csv-nek nevezzük, és van egy helyőrző, amely az Azure Digital Twins-példány gazdagépnevét jelöli. A minta emellett több csomagot is használ, amelyeket hozzáadhat a projekthez, hogy segítse ezt a folyamatot.

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

Futtatható ikergráf minta

Az alábbi futtatható kódrészlet a jelen cikk kapcsolati műveleteivel hoz létre egy ikergráfot digitális ikerpéldányokból és kapcsolatokból.

Mintaprojektfájlok beállítása

A kódrészlet két mintamodell-definíciót használ, a Room.json-t és a Floor.json-t. Ha le szeretné tölteni a modellfájlokat , hogy a kódban használhassa őket, az alábbi hivatkozásokkal közvetlenül a GitHub fájljaira léphet. Ezután kattintson a jobb gombbal a képernyő tetszőleges pontjára, válassza a Mentés másként lehetőséget a böngésző jobb oldali menüjében, és a Mentés másként ablakban mentse a fájlokat Room.json és Floor.json formátumban.

Ezután hozzon létre egy új konzolalkalmazás-projektet a Visual Studióban vagy a választott szerkesztőben.

Ezután másolja a futtatható minta következő kódját a projektbe:

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

Megjegyzés:

Jelenleg ismert probléma van a DefaultAzureCredential burkolóosztályt érintően, amely a hitelesítés során hibát okozhat. Ha ezt a problémát tapasztalja, a probléma megoldásához próbálja meg példányosítani DefaultAzureCredential a következő opcionális paramétert: new DefaultAzureCredential(new DefaultAzureCredentialOptions { ExcludeSharedTokenCacheCredential = true });

A problémával kapcsolatos további információkért tekintse meg az Azure Digital Twins ismert problémáit.

Projekt konfigurálása

Ezután hajtsa végre a következő lépéseket a projektkód konfigurálásához:

  1. Adja hozzá a korábban letöltött Room.json - és Floor.json-fájlokat a projekthez, és cserélje le a <path-to> kód helyőrzőit, hogy a program hol találja őket.

  2. Cserélje le a helyőrzőt <your-instance-hostname> az Azure Digital Twins-példány gazdagépnevére.

  3. Adjon hozzá két függőséget a projekthez, amelyekre szükség lesz az Azure Digital Twins használatához. Az első a .NET-hez készült Azure Digital Twins SDK csomagja, a második pedig az Azure-beli hitelesítést segítő eszközöket biztosít.

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

Ha közvetlenül szeretné futtatni a mintát, helyi hitelesítő adatokat is be kell állítania. A következő szakasz végigvezeti ezt a folyamatot.

Helyi Azure-hitelesítő adatok beállítása

Ez a minta a DefaultAzureCredential (a tár része) használatával hitelesíti a Azure.Identity felhasználókat az Azure Digital Twins-példánysal, amikor a helyi gépen futtatja. Az ügyfélalkalmazások Azure Digital Twins-hitelesítésének különböző módjairól az alkalmazáshitelesítési kód írása című témakörben olvashat bővebben.

Ezzel DefaultAzureCredentiala példával a minta hitelesítő adatokat keres a helyi környezetben, például egy Azure-bejelentkezést egy helyi Azure CLI-ben vagy a Visual Studióban vagy a Visual Studio Code-ban. Ezért helyileg kell bejelentkeznie az Azure-ba ezen mechanizmusok egyikével a minta hitelesítő adatainak beállításához.

Ha a Visual Studio vagy a Visual Studio Code használatával futtat kódmintákat, győződjön meg arról , hogy ugyanazokkal az Azure-hitelesítő adatokkal jelentkezett be a szerkesztőbe , amelyeket az Azure Digital Twins-példány eléréséhez használni szeretne. Ha helyi CLI-ablakot használ, futtassa a parancsot az az login Azure-fiókba való bejelentkezéshez. Ezt követően a kódminta futtatásakor automatikusan hitelesíteni kell.

Minta futtatása

Most, hogy befejezte a telepítést, futtathatja a mintakódprojektet.

A program konzolkimenete a következő:

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

Tipp.

Az ikergráf az ikerpéldányok közötti kapcsolatok létrehozásának fogalma. Ha meg szeretné tekinteni az ikergráf vizuális ábrázolását, tekintse meg a cikk Vizualizáció szakaszát.

További lépések

További információ az Azure Digital Twins ikergráfok lekérdezéséről: