إدارة التوائم الرقمية

يتم تمثيل الكيانات في بيئتك بواسطة التوائم الرقمية. قد تتضمن إدارة التوائم الرقمية الإنشاء والتعديل والإزالة.

تركز هذه المقالة على إدارة التوائم الرقمية؛ للعمل مع العلاقات والرسم البياني المزدوج ككل، راجع إدارة الرسم البياني المزدوج والعلاقات.

تلميح

تأتي جميع وظائف SDK في إصدارات متزامنة وغير متزامنة.

المتطلبات الأساسية

للعمل مع Azure Digital Twins في هذه المقالة، ستحتاج إلى مثيل Azure Digital Twins والأذونات المطلوبة لاستخدامه. إذا كان لديك بالفعل مثيل Azure Digital Twins تم إعداده، يمكنك استخدام هذا المثيل والتخطي إلى القسم التالي. وإلا، فاتبع الإرشادات الموجودة في إعداد نمذجة ومصادقة. تحتوي الإرشادات على معلومات لمساعدتك في التحقق من إكمال كل خطوة بنجاح.

بعد إعداد المثيل الخاص بك، دون اسم مضيف المثيل. يمكنك العثور على اسم المضيف في بوابة Azure.

واجهات المطور

تسلط هذه المقالة الضوء على كيفية إكمال عمليات الإدارة المختلفة باستخدام .NET (C#) SDK. يمكنك أيضا صياغة استدعاءات الإدارة نفسها هذه باستخدام حزم SDK للغة الأخرى الموضحة في واجهات برمجة تطبيقات Azure Digital Twins وSDKs.

تتضمن واجهات المطور الأخرى التي يمكن استخدامها لإكمال هذه العمليات ما يلي:

الرسوم المرئية

Azure Digital Twins Explorer هو أداة مرئية لاستكشاف البيانات في الرسم البياني Azure Digital Twins. يمكنك استخدام المستكشف لعرض نماذجك وتوائمك وعلاقاتك والاستعلام عنهما وتحريرهما.

للقراءة عن أداة Azure Digital Twins Explorer، راجع Azure Digital Twins Explorer. للحصول على خطوات مفصلة حول كيفية استخدام ميزاته، راجع استخدام Azure Digital Twins Explorer.

إليك الشكل الذي تبدو عليه المرئيات:

لقطة شاشة لمستكشف Azure Digital Twins تعرض نماذج نماذج وتوائم.

إنشاء توأم رقمي

لإنشاء توأم، يمكنك استخدام طريقة CreateOrReplaceDigitalTwinAsync() على عميل الخدمة مثل هذا:

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

لإنشاء توأم رقمي، عليك تقديم:

  • قيمة المعرف التي تريد تعيينها إلى التوأم الرقمي (تقوم بتعريف هذا المعرف عند إنشاء التوأم)
  • النموذج الذي تريد استخدامه
  • أي تهيئة مطلوبة للبيانات المزدوجة، بما في ذلك...
    • الخصائص (التهيئة اختيارية): يمكنك تعيين القيم الأولية لخصائص التوأم الرقمي إذا كنت تريد ذلك. يتم التعامل مع الخصائص على أنها اختيارية ويمكن تعيينها لاحقا، ولكن لاحظ أنها لن تظهر كجزء من التوأم حتى يتم تعيينها.
    • المكونات (التهيئة مطلوبة إذا كانت موجودة على توأم): إذا كان التوأم يحتوي على أي مكونات، فيجب تهيئتها عند إنشاء التوأم. يمكن أن تكون كائنات فارغة، ولكن المكونات نفسها يجب أن تكون موجودة.

يتم توفير النموذج وأي قيم خاصية أولية من خلال المعلمة initData ، وهي سلسلة JSON تحتوي على البيانات ذات الصلة. لمزيد من المعلومات حول هيكلة هذا الكائن، تابع إلى القسم التالي.

تلميح

بعد إنشاء توأم أو تحديثه، قد يكون هناك زمن انتقال يصل إلى 10 ثوان قبل أن تنعكس التغييرات في الاستعلامات. GetDigitalTwin لا تواجه واجهة برمجة التطبيقات (الموضحة لاحقا في هذه المقالة) هذا التأخير، لذلك إذا كنت بحاجة إلى استجابة فورية، فاستخدم استدعاء واجهة برمجة التطبيقات بدلا من الاستعلام لرؤية التوائم التي تم إنشاؤها حديثا.

تهيئة النموذج والخصائص

يمكنك تهيئة خصائص التوأم في وقت إنشاء التوأم.

تقبل واجهة برمجة تطبيقات إنشاء التوأم كائنا يتم تسلسله في وصف JSON صالح للخصائص المزدوجة. راجع Digital Twins والرسم البياني المزدوج للحصول على وصف لتنسيق JSON للتوأم.

أولا، يمكنك إنشاء كائن بيانات لتمثيل التوأم وبيانات الخاصية الخاصة به. يمكنك إنشاء كائن معلمة إما يدويا، أو باستخدام فئة مساعد متوفرة. فيما يلي مثال على كل منها.

إنشاء توائم باستخدام البيانات التي تم إنشاؤها يدويا

دون استخدام أي فئات مساعدة مخصصة، يمكنك تمثيل خصائص التوأم في Dictionary<string, object>، حيث string يكون هو اسم الخاصية و object هو كائن يمثل الخاصية وقيمتها.

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

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

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

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

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

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

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

إنشاء توائم مع فئة المساعد

تنيح لك فئة المساعد BasicDigitalTwin تخزين حقول الخصائص في كائن "مزدوج" مباشرةً. قد لا تزال ترغب في إنشاء قائمة الخصائص باستخدام Dictionary<string, object>، والتي يمكن إضافتها بعد ذلك إلى الكائن المزدوج كمباشرة CustomProperties .

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

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

إشعار

BasicDigitalTwin تأتي الكائنات مع Id حقل. يمكنك ترك هذا الحقل فارغا، ولكن إذا قمت بإضافة قيمة معرف، فإنه يحتاج إلى مطابقة معلمة المعرف التي تم تمريرها إلى CreateOrReplaceDigitalTwinAsync() الاستدعاء. على سبيل المثال:

twin.Id = "myRoomId";

إنشاء توائم بشكل مجمع باستخدام واجهة برمجة تطبيقات استيراد الوظائف

يمكنك استخدام واجهة برمجة تطبيقات استيراد المهام لإنشاء العديد من التوائم في وقت واحد في استدعاء API واحد. يتطلب هذا الأسلوب استخدام Azure Blob Storage، وكتابة الأذونات في مثيل Azure Digital Twins للتوائم والمهام المجمعة.

تلميح

تسمح واجهة برمجة تطبيقات استيراد المهام أيضا باستيراد النماذج والعلاقات في نفس الاستدعاء، لإنشاء جميع أجزاء الرسم البياني في وقت واحد. لمزيد من المعلومات حول هذه العملية، راجع تحميل النماذج والتوائم والعلاقات بشكل مجمع باستخدام واجهة برمجة تطبيقات استيراد المهام.

لاستيراد التوائم بشكل مجمع، تحتاج إلى هيكلة التوائم (وأي موارد أخرى مضمنة في مهمة الاستيراد المجمع) كملف NDJSON . Twins يأتي المقطع بعد Models المقطع (وقبل Relationships المقطع). يمكن أن تشير التوائم المعرفة في الملف إلى النماذج المحددة في هذا الملف أو الموجودة بالفعل في المثيل، ويمكن أن تتضمن اختياريا تهيئة خصائص التوأم.

يمكنك عرض مثال لملف استيراد ومشروع عينة لإنشاء هذه الملفات في مقدمة واجهة برمجة تطبيقات استيراد المهام.

بعد ذلك، يجب تحميل الملف إلى كائن ثنائي كبير الحجم للإلحاق في Azure Blob Storage. للحصول على إرشادات حول كيفية إنشاء حاوية تخزين Azure، راجع إنشاء حاوية. ثم قم بتحميل الملف باستخدام أسلوب التحميل المفضل لديك (بعض الخيارات هي الأمر AzCopy أو Azure CLI أو مدخل Microsoft Azure).

بمجرد تحميل ملف NDJSON إلى الحاوية، احصل على عنوان URL الخاص به داخل حاوية الكائن الثنائي كبير الحجم. ستستخدم هذه القيمة لاحقا في نص استدعاء واجهة برمجة التطبيقات للاستيراد المجمع.

فيما يلي لقطة شاشة تعرض قيمة عنوان URL لملف كائن ثنائي كبير الحجم في مدخل Microsoft Azure:

لقطة شاشة لمدخل Azure تعرض عنوان URL لملف في حاوية تخزين.

بعد ذلك، يمكن استخدام الملف في استدعاء واجهة برمجة تطبيقات استيراد المهام. يمكنك توفير عنوان URL لتخزين كائن ثنائي كبير الحجم لملف الإدخال، وعنوان URL جديد لتخزين كائن ثنائي كبير الحجم للإشارة إلى المكان الذي تريد تخزين سجل الإخراج فيه بعد إنشاء الخدمة له.

الحصول على البيانات لتوأم رقمي

يمكنك الوصول إلى تفاصيل أي توأم رقمي عن طريق استدعاء الطريقة GetDigitalTwin() على النحو التالي:

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

يقوم هذا الاستدعاء بإرجاع بيانات مزدوجة كنوع كائن مكتوب بقوة مثل BasicDigitalTwin. BasicDigitalTwin هي فئة مساعد تسلسل مضمنة مع SDK، والتي ترجع بيانات التعريف الأساسية المزدوجة والخصائص في النموذج الذي تم إعداده. يمكنك دائما إلغاء تسلسل البيانات المزدوجة باستخدام مكتبة JSON التي تختارها، مثل System.Text.Json أو Newtonsoft.Json. للوصول الأساسي إلى التوأم، ومع ذلك، يمكن لفئات المساعد أن تجعل هذا أكثر ملاءمة.

إشعار

BasicDigitalTwin يستخدم System.Text.Json السمات. لاستخدام BasicDigitalTwin مع DigitalTwinsClient، يجب إما تهيئة العميل باستخدام الدالة الإنشائية الافتراضية، أو، إذا كنت تريد تخصيص خيار التسلسل، فاستخدم JsonObjectSerializer.

BasicDigitalTwin تمنحك فئة المساعد أيضا حق الوصول إلى الخصائص المحددة على التوأم، من خلال Dictionary<string, object>. لسرد خصائص التوأم، يمكنك استخدام:

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

يتم إرجاع الخصائص التي تم تعيينها مرة واحدة على الأقل فقط عند استرداد توأم باستخدام GetDigitalTwin() الأسلوب .

تلميح

displayName بالنسبة إلى التوأم هو جزء من بيانات تعريف النموذج الخاصة به، لذلك لن يظهر عند الحصول على بيانات للمثيل المزدوج. لمشاهدة هذه القيمة، يمكنك استردادها من النموذج.

لاسترداد توائم متعددة باستخدام استدعاء API واحد، راجع أمثلة واجهة برمجة تطبيقات الاستعلام في الاستعلام عن الرسم البياني المزدوج.

ضع في اعتبارك النموذج التالي (المكتوب بلغة تعريف التوائم الرقمية (DTDL)) الذي يعرف القمر:

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

قد تبدو نتيجة الاتصال object result = await client.GetDigitalTwinAsync("my-moon"); على توأم من نوع القمر كما يلي:

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

يتم إرجاع الخصائص المحددة للتوائم الرقمية كخصائص ذات مستوى أعلى على التوأم الرقمي. يتم إرجاع بيانات التعريف أو معلومات النظام التي ليست جزءا من تعريف DTDL ببادئة $ . تتضمن خصائص بيانات التعريف القيم التالية:

  • $dtId: معرف التوأم الرقمي في مثيل Azure Digital Twins هذا
  • $etag: حقل HTTP قياسي تم تعيينه بواسطة خادم الويب. يتم تحديث هذا إلى قيمة جديدة في كل مرة يتم فيها تحديث التوأم، والتي يمكن أن تكون مفيدة لتحديد ما إذا كان قد تم تحديث بيانات التوأم على الخادم منذ فحص سابق. يمكنك استخدام If-Match لتنفيذ التحديثات والحذف التي لا تكتمل إلا إذا تطابق etag للكيان مع etag المتوفر. لمزيد من المعلومات حول هذه العمليات، راجع وثائق DigitalTwins Update وDy digitalTwins Delete.
  • $metadata: مجموعة من خصائص بيانات التعريف، والتي قد تتضمن ما يلي:
    • $model، DTMI لنموذج التوأم الرقمي.
    • lastUpdateTime للخصائص المزدوجة. هذا طابع زمني يشير إلى تاريخ ووقت معالجة Azure Digital Twins لرسالة تحديث الخاصية
    • sourceTime للخصائص المزدوجة. هذه خاصية اختيارية قابلة للكتابة تمثل الطابع الزمني عند ملاحظة تحديث الخاصية في العالم الحقيقي.

يمكنك قراءة المزيد حول الحقول المضمنة في التوأم الرقمي بتنسيق JSON التوأم الرقمي. يمكنك قراءة المزيد حول فئات مساعد التسلسل كما هو الحال BasicDigitalTwin في واجهات برمجة تطبيقات Azure Digital Twins وSDKs.

عرض جميع التوائم الرقمية

لعرض جميع التوائم الرقمية في مثيلك، استخدم استعلاما. يمكنك تشغيل استعلام باستخدام واجهات برمجة تطبيقات الاستعلام أو أوامر CLI.

فيما يلي نص الاستعلام الأساسي الذي يقوم بإرجاع قائمة بجميع التوائم الرقمية في المثيل:

SELECT * FROM DIGITALTWINS

تحديث التوأم الرقمي

لتحديث خصائص التوأم الرقمي، اكتب المعلومات التي تريد استبدالها بتنسيق JSON Patch . للحصول على قائمة كاملة بعمليات JSON Patch التي يمكن استخدامها، بما في ذلك replaceو add ، removeراجع عمليات JSON Patch.

بعد صياغة مستند JSON Patch الذي يحتوي على معلومات التحديث، مرر المستند إلى UpdateDigitalTwin() الأسلوب :

await client.UpdateDigitalTwinAsync(twinId, updateTwinData);

يمكن لاستدعاء تصحيح واحد تحديث العديد من الخصائص على توأم واحد كما تريد (حتى كل منهم). إذا كنت بحاجة إلى تحديث الخصائص عبر توائم متعددة، فأنت بحاجة إلى استدعاء تحديث منفصل لكل توأم.

تلميح

بعد إنشاء توأم أو تحديثه، قد يكون هناك زمن انتقال يصل إلى 10 ثوان قبل أن تنعكس التغييرات في الاستعلامات. GetDigitalTwin لا تواجه واجهة برمجة التطبيقات (الموضحة سابقا في هذه المقالة) هذا التأخير، لذا استخدم استدعاء واجهة برمجة التطبيقات بدلا من الاستعلام لرؤية التوائم المحدثة حديثا إذا كنت بحاجة إلى استجابة فورية.

فيما يلي مثال على التعليمات البرمجية ل JSON Patch. يحل هذا المستند محل قيم خاصية الكتلة ونصف القطر للتوائم الرقمية التي يتم تطبيقها عليه. يوضح هذا المثال عملية JSON Patch replace ، التي تحل محل قيمة خاصية موجودة.

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

عند تحديث توأم من مشروع تعليمة برمجية باستخدام .NET SDK، يمكنك إنشاء تصحيحات JSON باستخدام JsonPatchDocument الخاص ب Azure .NET SDK. فيما يلي مثال على إنشاء مستند JSON Patch واستخدامه UpdateDigitalTwin() في التعليمات البرمجية للمشروع.

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

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

تلميح

يمكنك الاحتفاظ بالطوابع الزمنية المصدر على التوائم الرقمية الخاصة بك عن طريق تحديث $metadata.<property-name>.sourceTime الحقل بالعملية الموضحة في هذا القسم. لمزيد من المعلومات حول هذا الحقل والحقول الأخرى القابلة للكتابة على التوائم الرقمية، راجع تنسيق JSON للتوأم الرقمي.

تحديث الخصائص الفرعية في مكونات التوأم الرقمي

تذكر أن النموذج قد يحتوي على مكونات، ما يسمح بتكونه من نماذج أخرى.

لتصحيح الخصائص في مكونات التوأم الرقمي، يمكنك استخدام بناء جملة المسار في JSON Patch:

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

تحديث الخصائص الفرعية في خصائص نوع الكائن

قد تحتوي النماذج على خصائص من نوع عنصر. قد يكون لهذه الكائنات خصائصها الخاصة، وقد ترغب في تحديث إحدى هذه الخصائص الفرعية التي تنتمي إلى خاصية نوع العنصر. تشبه هذه العملية عملية تحديث الخصائص الفرعية في المكونات، ولكنها قد تتطلب بعض الخطوات الإضافية.

ضع في اعتبارك نموذجا بخاصية من نوع الكائن، ObjectProperty. ObjectProperty يحتوي على خاصية سلسلة تسمى StringSubProperty.

عند إنشاء توأم باستخدام هذا النموذج، ليس من الضروري إنشاء مثيل في ObjectProperty ذلك الوقت. إذا لم يتم إنشاء مثيل لخاصية الكائن أثناء الإنشاء المزدوج، فلا يوجد مسار افتراضي تم إنشاؤه للوصول إليه ObjectProperty وله StringSubProperty لعملية تصحيح. تحتاج إلى إضافة المسار إلى ObjectProperty نفسك قبل أن تتمكن من تحديث خصائصه.

يمكن القيام بذلك من خلال عملية JSON Patch add ، مثل هذا:

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

إشعار

إذا كان ObjectProperty يحتوي على أكثر من خاصية واحدة، يجب تضمينها جميعا في value حقل هذه العملية، حتى إذا كنت تقوم بتحديث خاصية واحدة فقط:

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

بعد القيام بذلك مرة واحدة، مسار إلى StringSubProperty موجود، ويمكن تحديثه مباشرة من الآن فصاعدا مع عملية نموذجية replace :

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

على الرغم من أن الخطوة الأولى ليست ضرورية في الحالات التي تم إنشاء مثيل لها ObjectProperty عند إنشاء التوأم، فمن المستحسن استخدامه في كل مرة تقوم فيها بتحديث خاصية فرعية للمرة الأولى، حيث قد لا تعرف دائما بشكل مؤكد ما إذا كان قد تم إنشاء مثيل لخاصية الكائن في البداية أم لا.

تحديث نموذج التوأم الرقمي

يمكن أيضًا استخدام الوظيفة UpdateDigitalTwin() لترحيل التوأم الرقمي إلى نموذج مختلف.

على سبيل المثال، ضع في اعتبارك مستند JSON Patch التالي الذي يحل محل حقل بيانات التعريف $model للتوأم الرقمي:

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

تنجح هذه العملية فقط إذا كان التوأم الرقمي الذي يتم تعديله بواسطة التصحيح يتوافق مع النموذج الجديد.

تأمل المثال التالي:

  1. تخيل توأماً رقمياً بنموذج foo_old. يحدد foo_old كتلة خاصية مطلوبة.
  2. يحدد النموذج الجديد foo_new كتلة الخاصية، ويضيف درجة حرارة خاصية مطلوبة جديدة.
  3. بعد التصحيح، يجب أن يتمتع التوأم الرقمي بخاصية الكتلة ودرجة الحرارة.

يحتاج التصحيح الخاص بهذا الموقف إلى تحديث كل من الطراز وخاصية درجة حرارة التوأم، مثل هذا:

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

تحديث مصدر وقت الخاصية

قد تقرر اختياريا استخدام الحقل في sourceTime الخصائص المزدوجة لتسجيل الطوابع الزمنية عند ملاحظة تحديثات الخصائص في العالم الحقيقي. يدعم sourceTime Azure Digital Twins أصلا في بيانات التعريف لكل خاصية مزدوجة. sourceTime يجب أن تتوافق القيمة مع تنسيق التاريخ والوقت ISO 8601. لمزيد من المعلومات حول هذا الحقل والحقول الأخرى على التوائم الرقمية، راجع تنسيق JSON التوأم الرقمي.

الحد الأدنى من إصدار REST API الثابت لدعم هذا الحقل هو إصدار 2022-05-31 . للعمل مع هذا الحقل باستخدام Azure Digital Twins SDKs، نوصي باستخدام أحدث إصدار من SDK للتأكد من تضمين هذا الحقل.

فيما يلي مثال على مستند JSON Patch الذي يقوم بتحديث كل من قيمة وحقل sourceTime الخاصية Temperature :

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

لتحديث الحقل على sourceTime خاصية جزء من مكون، قم بتضمين المكون في بداية المسار. في المثال أعلاه، يمكنك القيام بذلك عن طريق تغيير قيمة المسار من /$metadata/Temperature/sourceTime إلى myComponent/$metadata/Temperature/sourceTime.

إشعار

إذا قمت بتحديث كل من sourceTime القيمة و على خاصية، ثم قمت لاحقا بتحديث قيمة الخاصية فقط، sourceTime سيبقى الطابع الزمني من التحديث الأول.

معالجة مكالمات التحديث المتعارضة

يضمن Azure Digital Twins معالجة جميع الطلبات الواردة واحدا تلو الآخر. وهذا يعني أنه حتى إذا حاولت دوال متعددة تحديث نفس الخاصية على توأم في نفس الوقت، ليست هناك حاجة لكتابة رمز تأمين صريح للتعامل مع التعارض.

هذا السلوك على أساس كل توأم.

على سبيل المثال، تخيل سيناريو تصل فيه هذه الاستدعاءات الثلاثة في نفس الوقت:

  • كتابة الخاصية A على Twin1
  • كتابة الخاصية B على Twin1
  • كتابة الخاصية A على Twin2

يتم تنفيذ الاستدعاءين اللذين يعدلان Twin1 واحدا تلو الآخر، ويتم إنشاء رسائل التغيير لكل تغيير. يمكن تنفيذ استدعاء تعديل Twin2 بشكل متزامن دون أي تعارض، بمجرد وصوله.

حذف التوأم الرقمي

يمكنك حذف التوائم باستخدام طريقة DeleteDigitalTwin(). ومع ذلك، يمكنك حذف التوأم فقط عندما لا يكون لديه المزيد من العلاقات. لذا، احذف علاقات التوأم الواردة والصادرة أولاً.

فيما يلي مثال على التعليمات البرمجية لحذف التوائم وعلاقاتهم. DeleteDigitalTwin يتم تمييز استدعاء SDK لتوضيح مكان وقوعه في سياق المثال الأوسع.

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

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

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

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

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

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

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

حذف جميع التوائم الرقمية

للحصول على مثال حول كيفية حذف جميع التوائم في وقت واحد، نزل نموذج التطبيق المستخدم في استكشاف الأساسيات باستخدام نموذج تطبيق العميل. يقوم ملف CommandLoop.cs بذلك في دالةCommandDeleteAllTwins().

إشعار

إذا كنت ترغب في حذف جميع النماذج والتوائم والعلاقات في مثيل في وقت واحد، فاستخدم واجهة برمجة تطبيقات Delete Jobs.

نموذج رمز التوأم الرقمي القابل للتشغيل

يمكنك استخدام نموذج التعليمات البرمجية القابلة للتشغيل أدناه لإنشاء توأم وتحديث تفاصيله وحذف التوأم.

إعداد نموذج ملفات المشروع

يستخدم القصاصة البرمجية نموذج تعريف نموذج، Room.json. لتنزيل ملف النموذج حتى تتمكن من استخدامه في التعليمات البرمجية الخاصة بك، استخدم هذا الارتباط للانتقال مباشرة إلى الملف في GitHub. بعد ذلك، انقر بزر الماوس الأيمن فوق أي مكان على الشاشة، وحدد حفظ باسم في قائمة النقر بزر الماوس الأيمن في المستعرض، واستخدم نافذة حفظ باسم لحفظ الملف ك Room.json.

بعد ذلك، قم بإنشاء مشروع تطبيق وحدة تحكم جديد في Visual Studio أو المحرر الذي تختاره.

ثم انسخ التعليمات البرمجية التالية للعينة القابلة للتشغيل في مشروعك:

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

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

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

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

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

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

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

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

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

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

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

            return twin;
        }

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

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

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

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

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

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

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

    }
}

إشعار

توجد حاليا مشكلة معروفة تؤثر على DefaultAzureCredential فئة برنامج التضمين قد تؤدي إلى حدوث خطأ أثناء المصادقة. إذا واجهت هذه المشكلة، يمكنك محاولة إنشاء DefaultAzureCredential مثيل باستخدام المعلمة الاختيارية التالية لحلها: new DefaultAzureCredential(new DefaultAzureCredentialOptions { ExcludeSharedTokenCacheCredential = true });

لمزيد من المعلومات حول هذه المشكلة، راجع المشكلات المعروفة في Azure Digital Twins.

تكوين المشروع

بعد ذلك، أكمل الخطوات التالية لتكوين التعليمات البرمجية للمشروع:

  1. أضف ملف Room.json الذي قمت بتنزيله مسبقا إلى مشروعك، واستبدل <path-to> العنصر النائب في التعليمات البرمجية لإخبار البرنامج بمكان العثور عليه.

  2. استبدل العنصر النائب <your-instance-hostname> باسم مضيف مثيل Azure Digital Twins.

  3. أضف تبعيتين إلى مشروعك مطلوبين للعمل مع Azure Digital Twins. الأول هو حزمة Azure Digital Twins SDK ل .NET، والثاني يوفر أدوات للمساعدة في المصادقة مقابل Azure.

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

تحتاج أيضا إلى إعداد بيانات الاعتماد المحلية إذا كنت تريد تشغيل العينة مباشرة. المقطع التالي يستعرض هذا.

إعداد بيانات اعتماد Azure المحلية

تستخدم هذه العينة DefaultAzureCredential (جزء من مكتبة Azure.Identity) لمصادقة المستخدمين مع مثيل Azure Digital Twins عند تشغيله على جهازك المحلي. لمزيد من المعلومات حول الطرق المختلفة التي يمكن لتطبيق العميل مصادقتها باستخدام Azure Digital Twins، راجع كتابة تعليمات برمجية لمصادقة التطبيق.

سيبحث النموذج باستخدام DefaultAzureCredential عن بيانات اعتماد في بيئتك المحلية، مثل تسجيل الدخول إلى Microsoft Azure في Azure CLI محلي أو في Visual Studio أو Visual Studio Code. ولهذا السبب، يجب تسجيل الدخول محلياً إلى Microsoft Azure من خلال أحد هذه الآليات المخصصة لإعداد بيانات الاعتماد للنموذج.

إذا كنت تستخدم Visual Studio أو Visual Studio Code لتشغيل نماذج التعليمات البرمجية، فتأكد من تسجيل الدخول إلى هذا المحرر بنفس بيانات اعتماد Azure التي تريد استخدامها للوصول إلى مثيل Azure Digital Twins. إذا كنت تستخدم نافذة CLI محلية az login ، فقم بتشغيل الأمر لتسجيل الدخول إلى حساب Azure الخاص بك. بعد ذلك، عند تشغيل نموذج التعليمات البرمجية، يجب أن تتم مصادقتك تلقائيا.

تشغيل تطبيق العرض التوضيحي

الآن بعد اكتمال الإعداد، يمكنك تشغيل نموذج مشروع التعليمات البرمجية.

فيما يلي إخراج وحدة التحكم للبرنامج أعلاه:

لقطة شاشة لإخراج وحدة التحكم تظهر إنشاء التوأم وتحديثه وحذفه.

الخطوات التالية

تعرف على كيفية إنشاء وإدارة العلاقات بين التوائم الرقمية: