أين تخزن البيانات؟

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




أعطي الكلمة للمؤلف أليكسي بلوتنيكوف .

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

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

نبدأ صغيرة - ما هي السحابة؟ لأول مرة سمعت عن السحابة مرة أخرى في عام 2012 ثم تم استخدام عبارة "الحوسبة السحابية" في أغلب الأحيان. كانت الفكرة الأولية لمثل هذه الحسابات هي توزيع أعمال الحوسبة بين الأجهزة المختلفة البعيدة عن بعضها البعض. تحدث بشكل مثير للإعجاب بشكل خاص عن المستقبل ، حيث سيتم معالجة حتى أصعب المهام في بضع لحظات بسبب حقيقة أن الحسابات سيتم توزيعها بين جميع أجهزة الكمبيوتر في العالم.

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

بناءً على ما سبق ، يمكننا أن نفترض أنه عندما تسمع كلمة "سحابة" ، يمكنك إدراكها على أنها "استضافة" مألوفة ، والفرق الوحيد هو أنه يمكن توسيع قوة السحابة دون أي جهد إضافي من جانبك.

السؤال الثاني الذي قد يكون لديك هو لماذا أزور؟ "نظرًا لأن هذه مقالة على مدونة Microsoft ، فإن المؤلف سيتحدث فقط عن منتجاتهم" - كما تقول ، وستكون مخطئًا. الدوافع لاستخدام Azure أكثر شيوعًا - نظرًا لأن هذا منتج من منتجات Microsoft ، فإنه يتمتع بأعلى درجة ممكنة من التكامل مع منتجاتهم الأخرى ، والتي يتم تطوير تطبيقي من خلالها.

ومع ذلك ، ألاحظ أن الشركة تبذل قصارى جهدها لجعل استخدام Azure جذابًا لمطوري Android أو iOS. حسنًا ، المشكلة الأخيرة ، ولكن ليس الأقل ، هي تكلفة استخدام السحابة. نظرًا لأنني حامل لاشتراك في BizSpark ، فقد مُنحت قرضًا شهريًا لحقيبة ذات فائدة أكثر من تغطية احتياجات السحابة الخاصة بي ، على الرغم من أن الشروط المقدمة على أساس مجاني يمكن أن تغطي أيضًا معظم احتياجات مطور خاص.

الآن دعنا ننتقل إلى التحديد المباشر لآلية التزامن وتخزين البيانات. لن أكون ماكرًا ، بصفتي شخصًا من العصاميين ، غالبًا ما أتعامل مع التقنيات التي لم تكن لدي أي فكرة عنها قبل أن أتعرف على UWP ، لقد قمت بحل مشاكل مماثلة باستخدام قواعد بيانات SQL.

ومع ذلك ، لا تملك UWP الوسائل للعمل مع SQL DBMSs الكلاسيكية ، ولكن SQLite يتم تقديمه كبديل ، وبعد أن بدأت دراستي ، اكتشفت أن قاعدة البيانات هذه مدمجة ، وهي مناسبة للتخزين والاستخدام المناسبين للبيانات المحلية ، ولكنها غير مناسبة تمامًا لوضع البيانات في المخزن البعيد. بالفعل في عملية كتابة هذه المقالة ، عندما تم اختيار التكنولوجيا اللازمة ، صادفت أحد حلول Azure في مجال تطوير تطبيقات الهاتف المحمول ، والذي يسمح لك بمزامنة البيانات من جدول SQLite بين الأجهزة ، ولكن بعد التفكير في الأمر بعناية ، بقيت على الاختيار الأولي.

بالمناسبة ، لم يكن الاختيار الأولي أمرًا صعبًا ، حيث طلبت Microsoft بأدب قائمة من التقنيات التي قد يضطر مطور UWP إلى مواجهتها. في أحدث إصدارات Visual Studio ، عند إنشاء مشروع UWP جديد ، سترى صفحة تحتوي على توصيات للبدء ، حيث يقرأ أحد الروابط "إضافة خدمة موصى بها". من خلال النقر على هذا الرابط ، تفتح علامة التبويب "توصيل الخدمة" ونرى بالفعل خيار "التخزين السحابي مع خدمة تخزين Azure".



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

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

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

بادئ ذي بدء ، دعنا نكتشف كيفية إنشاء جدول NoSQL:

1. قم بتسجيل حساب Azure مجاني . إذا كان لديك اشتراك MSDN أو BizSpark وتم تنشيطه بالفعل في Azure ، فيمكنك تخطي هذه الخطوة. يمنحك الحساب المجاني قرضًا بقيمة 200 دولار أمريكي للشهر الأول ثم الوصول المجاني إلى قدر معين من الموارد لمعظم خدمات Azure. تتم ترجمته إلى لغة مفهومة ، ويتم كل شيء بطريقة لن تضطر إلى الدفع حتى يكسب منتجك ما يكفي لتغطية النفقات ، ناهيك عن استخدام Azure للتعليم الذاتي.

ولكن حتى إذا تجاوزت العتبة المجانية ، فإن أسعار تخزين الجدول تكون أكثر ولاءً بكثير من كمية مماثلة من قواعد بيانات SQL. على سبيل المثال ، في وقت كتابة هذا المقال ، قمت بإنشاء جدولين ، حتى الآن بإدخال واحد فقط. طوال 18 يومًا من الفترة المشمولة بالتقرير ، لجأت إليها في المتوسط ​​20-30 مرة في اليوم وتم شطب كوبيلتين من حساب الائتمان لهذه الفترة. من خلال زيادة هذه التكاليف للحجم المخطط ، أدركت أنها تغطي أكثر من الدخل المحتمل من التطبيق.

2. الآن بعد أن أصبح لديك حساب في Azure ، ننتقل إلى إنشاء حساب تخزين.



يمكنك القيام بذلك كله من نفس صفحة اتصال خدمات Visual Studio ، التي وصفتها أعلاه. إذا أغلقت هذه الصفحة فجأة ، يمكنك فتحها بالنقر المزدوج على "الخدمات المتصلة" في مستكشف الحلول. بعد تحديد الخدمة المطلوبة ، سيتم فتح نافذة تحتوي على حسابات التخزين المتاحة ، ولإضافة واحدة جديدة ، انقر فوق الزر المقابل.

في النافذة الجديدة ، ستحتاج إلى تنفيذ الخطوات التالية:

  • للبدء ، ستحتاج إلى تسجيل الدخول باستخدام حساب Microsoft الخاص بك. تحتاج إلى استخدام الحساب الذي ترتبط به اشتراكاتك أو حساب Azure مجاني.
  • بعد تسجيل الدخول إلى حسابك ، سيظهر اشتراكك (أ) في حقل "الاشتراك". كل شيء بسيط مع الاختيار ، لذلك التعليقات غير ضرورية.
  • في حقل "الاسم" ، حدد الاسم المطلوب لخدمة التخزين. نظرًا لأن هذا هو أيضًا اسم نطاق الخدمة ، يجب أن يكون فريدًا في جميع الحسابات المتاحة في Azure ، وليس فقط داخل حسابك.
  • سيتطلب منك حقل "فئة السعر" أن تفهم الاختلافات بين النظام الأساسي السحابي والاستضافة التقليدية ، لأنه بالنقر على الرابط الموجود أسفل الحقل ، يمكنك رؤية قائمة بالأسعار ، ولكن ليس تفسيرًا واضحًا ، يمنحك كل خيار. بالطبع ، في براري روابط أقسام الموقع ، يمكنك العثور على معلومات شاملة حول جميع هذه الاختصارات مثل GRS و LRS ، ولكن هذا غير ضروري للمطور العادي. يكفي أن نفهم أنه كلما كانت التعريفة أكثر تكلفة ، كلما زادت مشاركة مراكز البيانات في معالجة بياناتك وتخزينها وزادت احتمالية سلامتها. بالنسبة للمشروع الصغير ، فإن أدنى معدل LRS جيد.
  • "مجموعة الموارد" هي مزيج من العديد من خدمات Azure لإدارة واحدة. في حالتنا ، قم بإنشاء اسم جديد ، مع تعيين أي اسم مألوف والمضي قدمًا.
  • آخر شيء تختاره هو "الموقع" لخدمتك. يُقصد بالموقع الموقع الفعلي لمراكز البيانات التي ستكون مسؤولة عن العمل مع بياناتنا. يرجى ملاحظة أنني أتحدث بصيغة الجمع ، لأنه في منطقة واحدة يمكن أن يكون هناك العديد من مراكز البيانات ويمكن توزيع العمل بينها (في حالة اختيار فئة سعرية مشورة). اختر الخيار الأقرب إلى قاعدة المستخدمين الأساسية. ومع ذلك ، إذا كنت تخطط للنمو على نطاق العالم كله وتحتاج إلى أقصى استجابة في أي مكان في العالم ، فلا أحد يزعجك لكل نسخة إقليمية من التطبيق لإنشاء حساب تخزين منفصل وتنفيذ مزامنة البيانات بينهما. إنها مستوى عال من القابلية للتوسعة وهي الميزة الرئيسية للسحابة.

3. بعد إنشاء حساب التخزين ، ستتم إضافته إلى القائمة ويمكنك المتابعة بالنقر فوق الزر "إضافة". ستكون نتيجة هذا الإجراء إضافة حزمة NuGet للعمل مع Azure إلى المشروع وحفظ سلسلة الاتصال في ملف app.config للمشروع.

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

4. يبقى الآن إنشاء جدول والبدء في العمل معه. وهنا يبدأ العمل الفردي بالاعتماد مباشرة على المهام.

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

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

الاستنتاج من هذا بسيط للغاية - لا يزعج أحد بتخزين إعدادات جميع المستخدمين في جدول واحد ، الشيء الرئيسي هو أن زوج القيم في عمودين PartitionKey و RowKey فريدان داخل الجدول. يتم تنفيذ هذا مرة أخرى في مشروعي ، حيث أن معرف المستخدم سيكون بمثابة PartitionKey ، على سبيل المثال ، السلسلة "UserName" مثل RowKey ، والتي ستسمح لنا بتحديد السجل الفريد الذي يتم تخزين اسم المستخدم فيه. ولكن كما قلت أعلاه ، نحتاج إلى الموازنة بين جميع الإيجابيات والسلبيات ، لذلك دعونا نزن:

  • جدول "لكل" جدول منفصل لكل بيانات المستخدم هو الراحة في إدراك بنية البيانات. إذا أخذنا الجدول كمجلد يحتوي على ملفات ، فمن المنطقي أن تكون جميع ملفات مستخدم واحد في نفس المجلد وأكثر شيوعًا للعمل مع مثل هذه البنية.
  • جميع العوامل الأخرى "ضد" جدول منفصل. بيانات المستخدم داخل جدول منفصل - هذا دقيق بشكل ملائم حتى يكون عدد هذه الجداول بالآلاف. نظرًا لأن حساب التخزين أعلى من الجدول ، فلا يتم توفير أي مجموعات أخرى لهم.

    نظرًا لقاعدة المستخدمين المحتملين ، فإننا نخاطر بالغرق في آلاف الجداول الفردية ، ونفقد تلك التي لها أي قيمة ذات أولوية. في الوقت نفسه ، يؤدي تخزين إعدادات جميع المستخدمين في جدول واحد إلى تبسيط الإدارة والعمل مع البيانات من أجل جمع المعلومات الإحصائية أو تنفيذ الوظائف الاجتماعية.

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

لذا ، عندما اكتشفت بنية تخزين البيانات ، دعنا نضيف جدولًا جديدًا أخيرًا. نظرًا لأننا رفضنا إنشائه على مستوى الرمز ، يبقى خياران: من خلال بوابة الويب Azure أو باستخدام أداة Microsoft Azure Storage Explorer الخاصة ، والتي يمكن تنزيلها من storageexplorer.com. في كلتا الحالتين ، من الضروري تحديد حساب التخزين المطلوب وفي قسم "خدمة الجداول / الجداول" حدد "+ جدول / إنشاء جدول". في مربع الحوار الذي يظهر ، أدخل الاسم المطلوب وقم بتنفيذ التغييرات.



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

العمليات الرئيسية التي سأقوم بها مع الجدول هي إدراج واستخراج الصفوف ، والتي تسمى "الكيانات" في مصطلحات تخزين الجدول. يسهل فهم هذا المصطلح عندما تدرك أنه لإدراج كيان واسترداده ، ستحتاج إلى تعيينه فئة موروثة من TableEntity من Microsoft.WindowsAzure.Storage.Table. ستحتوي الفئة اللاحقة بالفعل على بعض الحقول المطلوبة ، على سبيل المثال ، PartitionKey (اسم القسم) و RowKey (اسم السطر) ، وستكون تلك الحقول التي ننفذها بشكل مستقل أعمدة في السطر (خصائص الكيان).

ضع في اعتبارك مثالاً على جدول يتم فيه تخزين قائمة بجميع اللاعبين الذين يحملون اسمهم وصورتهم الرمزية وبلدهم.

    : Imports Microsoft.WindowsAzure.Storage Imports Microsoft.WindowsAzure.Storage.Table 

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

 Public Class AzureWorker Private Const AzureStorageConnectionString As String = "  ,     app.config" Private Const GamerListTableNameString As String = "GamerList" '    … End Class 

نحتاج الآن إلى إنشاء فئة سنقوم بتعيينها للكيان (الصف) داخل الجدول:

  Private Class GamerListClodTableDataClass Inherits TableEntity Public Const RowKeyValue As String = "UserID" Public Sub New () RowKey = RowKeyValue End Sub Public Property UserName As String = "" Public Property UserountryID As String = "" Public Property UserAvatar As String = "" End Class 

يجب أن تكون الفئة المراد تعيينها موروثة من TableEntity وتحتوي على حقول للبيانات التي نخطط لوضعها في الجدول. لاحظ أن تعيين قيم مفتاح صف أو مفتاح تقسيم على مستوى الفصل ليس ضروريًا ، ولكن في حالتي ، يتم تعيين مفتاح الصف لأنه غير قابل للتغيير بغض النظر عن المدخلات الأخرى.

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

المرحلة التحضيرية الأخيرة قبل الاستعلامات المباشرة للجدول هي إنشاء كائن في دالة منفصلة:

  Private Shared Function GetCloudTable(tableName As String) As CloudTable Dim storageAccount As CloudStorageAccount = CloudStorageAccount.Parse(AzureStorageConnectionString) Dim tableClient As CloudTableClient = storageAccount.CreateCloudTableClient() Dim table As CloudTable = tableClient.GetTableReference(tableName) Return table End Function 

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

أخيرًا ، دعنا ننتقل إلى العمل مباشرةً مع الجدول ونبدأ بحفظ بيانات المستخدم الحالية:

  Public Shared Async Function SavedOrUpdateUserData(u As UserManager) As Task(Of Boolean) Dim table As CloudTable = GetCloudTable(GamerListTableNameString) Try If Await table.ExistsAsync Then Dim UserDataClodTableData As New GamerListClodTableDataClass With {.PartitionKey = u.UserId, .UserName = u.UserName.Trim, .UserountryID = u.UserountryID, .UserAvatar = "https://apis.live.net/v5.0/" & u.UserId & "/picture"} Dim insertOperation As TableOperation = TableOperation.InsertOrReplace(UserDataClodTableData) Await table.ExecuteAsync(insertOperation) Return True End If Catch ex As Exception End Try Return False End Function 

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

للاستفسارات حول الجدول ، تحتاج أولاً إلى إنشاء كائن باستخدام سلسلة الاتصال إلى المستودع واسم الجدول (وضعنا هذه العملية في دالة منفصلة في وقت سابق). بعد ذلك ، يجب عليك التحقق من وجود الجدول ، وعلى الرغم من أننا على يقين من أن لدينا جدول بهذا الاسم ، فقد يحدث خطأ ، على سبيل المثال ، بسبب نقص الاتصال بالشبكة أو بسبب فشل في السحابة (وهذا هو السبب في وضع هذا الرمز في Try / block قبض). بعد ذلك ، قبل الكتابة إلى الجدول ، تحتاج إلى إنشاء مثيل لفئة UserDataClodTableData وتعيين القيمة المطلوبة لحقولها ثم إنشاء عملية InsertOrReplace فقط. كما يمكنك التخمين من اسم العملية ، ستقوم بإدراج صف جديد في الجدول إذا لم تكن الصفوف التي تحتوي على نفس زوج من PartitionKey و RowKey موجودة في الجدول وستستبدل البيانات إذا كان هذا الصف موجودًا بالفعل. حسنًا ، سيقوم فريق ExecuteAsync النهائي ، في الواقع ، بتنفيذ الإجراء المخطط على جانب تخزين الطاولة.

قراءة البيانات من الجدول سهلة مثل كتابتها. دعنا ، على سبيل المثال ، نطلب اسم مستخدم:

  Public Shared Async Function GetUserName(id As String) As Task(Of String) Dim table As CloudTable = GetCloudTable(GamerListTableNameString) Try If Await table.ExistsAsync Then Dim retrieveOperation As TableOperation = TableOperation.Retrieve(Of GamerListClodTableDataClass)(id, GamerListClodTableDataClass.RowKeyValue) Dim retrievedResult As TableResult = Await table.ExecuteAsync(retrieveOperation) If retrievedResult.Result IsNot Nothing Then Return CType(retrievedResult.Result, GamerListClodTableDataClass).UserName End If End If Catch ex As Exception End Try Return "" End Function 

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

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

المثال أعلاه هو الأكثر مثالية من وجهة نظر سرعة الاستعلام ، حيث من المرجح أن يجد نظام العنونة كيانًا على طول المسار "اسم التخزين \ اسم الجدول \ PartitionKey + RowKey" ، ومع ذلك ، للحصول على اسم واحد فقط ، نقوم بتحميل الكيان بأكمله ككل ، وهو أمر غير مفيد على كمية البيانات المنقولة.

ما يلي هو رمز وظيفة معدلة مع مراعاة الحد الأقصى من الاستعلام الأمثل:

  Public Shared Async Function GetUserName(id As String) As Task(Of String) Dim table As CloudTable = GetCloudTable(GamerListTableNameString) Try If Await table.ExistsAsync Then Dim projectionQuery As TableQuery(Of DynamicTableEntity) = New TableQuery(Of DynamicTableEntity)().Where(TableQuery.CombineFilters(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, id), "and", TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.Equal, GamerListClodTableDataClass.RowKeyValue))).Select({"UserName"}) Dim resolver As EntityResolver(Of String) = Function(pk, rk, ts, props, etag) Return props("UserName").StringValue End Function Dim result As TableQuerySegment(Of String) = Await table.ExecuteQuerySegmentedAsync(projectionQuery, resolver, Nothing) If result.Count > 0 Then Return result(0) End If End If Catch ex As Exception End Try Return "" End Function 

بدلاً من إنشاء كائن عملية ، نقوم في هذا الرمز بإنشاء كائن طلب يحتوي على عدة طرق لتحديد ما يجب الحصول عليه نتيجة لذلك. ينشئ أسلوب Where عامل تصفية يشير إلى الحاجة إلى إرجاع تلك الصفوف فقط التي يتساوى فيها PartitionKey و RowKey مع القيم المحددة ، ويشير التحديد التالي إلى أنه يجب تحديد عمود UserName فقط.

مع مثل هذا الاستعلام ، لا معنى لمقارنة النتيجة مع أي فئة ، وبالتالي ، يتم استخدام IDictionary كقيمة إرجاع ، حيث يكون المفتاح هو اسم العمود ، والقيمة هي محتوياته. نظرًا لأن الوظيفة ExecuteQuerySegmentedAsync لا تعرف نتيجة تنفيذها ، فمن الممكن (وفي هذه الحالة ضرورية) تمرير مفوض EntityResolver ، والذي يشير إلى دالة تأخذ القيمة المطلوبة من القاموس. تصبح نتيجة كل هذا TableQuerySegment في الفهرس الأول الذي يتم تخزين اسم المستخدم المطلوب منه.

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

هام! تستخدم مقالات الارتباط رمزًا لتطبيقات .NET الكلاسيكية وتختلف عن تطبيق UWP. لحسن الحظ ، هذا الاختلاف ليس مهمًا ونظائرها بديهية (غالبًا ما تكون الاختلافات في بادئة Async).

في الختام ، سأشارك نتائج استخدام تخزين Azure في مشروعي في الوقت الحالي. في البداية ، بعد استلام معرف المستخدم وتنزيل البيانات من Live ID ، أقترح عليه اختيار اسم مستعار (لقب) في حالة عدم تناسب الاسم المخزن في ملف التعريف. ثم يتم حفظ اللقب الذي تم إدخاله في فئة UserManager بدلاً من الفئة القياسية ، ويتم حفظ جميع هذه البيانات في جدول GamerList. في البداية التالية ، يتم استلام معرف المستخدم في الخلفية ويطلب اسم مستعار من المستودع. نتيجة لذلك ، يرى المستخدم لقبه في اللعبة ، وليس الاسم من ملف التعريف القياسي.

أيضًا في المستقبل ، سيكون الجدول الذي يحتوي على قائمة بالمستخدمين مفيدًا لإدخال الوظائف الاجتماعية في اللعبة ، والآن ، توصلت إلى تطبيق واحد على الأقل لهذه البيانات. في تنفيذ هذه المهمة ، ستساعدني أدوات Azure مثل Queue Storage و Azure Functions مرة أخرى ، ولكن سأتحدث عن هذا في إحدى المقالات التالية.

Source: https://habr.com/ru/post/ar414261/


All Articles