باستخدام SQLite في الوحدة (الوحدة + SQLite)

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

ما هو سكليتي ولماذا نحتاجه؟


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

كيفية العمل مع سكليتي؟


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

إنشاء وملء قاعدة بيانات الاختبار


نقوم بإنشاء قاعدة بيانات في Assets / StreamingAssets لمشروعنا (لدي db.bytes ، نظرًا لأن Unity تتفهم فقط *. بايت لقواعد البيانات ، سنستخدم هذا الامتداد). على سبيل المثال ، قمت بإنشاء قاعدة بيانات كهذه بالجداول التالية:

1) الجدول "لاعب" ، الذي يصف جوهر اللاعب:

CREATE TABLE "Player" ( "id_player" INTEGER NOT NULL, "nickname" TEXT NOT NULL, PRIMARY KEY("id_player") ); 

معبأ بالبيانات التالية:



2) جدول "النتائج" ، والذي يتم تقديمه لزيادة مستوى تطبيع قاعدة البيانات

 CREATE TABLE "Scores" ( "id" INTEGER NOT NULL, "id_player" INTEGER NOT NULL, "score" INTEGER NOT NULL, PRIMARY KEY("id"), FOREIGN KEY("id_player") REFERENCES "Player"("id_player") ); 

معبأ بالبيانات التالية:



ربط المكتبات


نقوم بإنشاء قاعدة بيانات في Assets / StreamingAssets لمشروعنا (لدي db.bytes) ، ثم نحتاج إلى توصيل المكتبات للعمل مع قاعدة البيانات هذه. قم بتنزيل ملف sqlite3.dll من الموقع الرسمي للعمل مع SQLite في Windows. استغرق الأمر مني يومين لتكوين أصدقاء ACBD مع Android ، نظرًا لأنه تبين أن المكتبة المشار إليها في هذه المقالة لا تعمل ، وأنا شخصياً لم أتمكن من العمل معها على Android ، فقد تصاعدت الأخطاء باستمرار ، ولهذا قمت بتحميل هذا وجدت في مكان ما على الإنترنت نسخة من المكتبة للأندرويد. نحن نضع المكتبات هنا - Assets / Plugins / sqlite.dll و Assets / Plugins / Android / sqlite.so .

بعد كل هذه المعالجات ، انسخ System.Data.dll و Mono.Data.Sqlite.dll من C: \ Program Files (x86) \ Unity \ Editor \ Data \ Mono \ lib \ mono \ 2.0 ولصق الأصول / الإضافات لمشروع الوحدة الخاص بك. أريد أن أشير إلى أنه في إصدار 2018 ، قد تكتب Unity أن System.Data.dll متصل بالفعل ويوجد تعارض بين ملفين متطابقين. في الواقع ، يتم حل هذا ببساطة ، ونحن لا نحذف System.Data.dll المدرجة حديثا.

يجب أن يكون هيكل المكتبات كما يلي:

الأصول / الإضافات / Mono.Data.Sqlite.dll - هناك حاجة فقط :)
الأصول / الإضافات / System.Data.dll - سبب مماثل
الأصول / الإضافات / sqlite3.dll - للعمل مع SQLite على ويندوز
الأصول / الإضافات / Android / libsqlite3.so - للعمل مع SQLite على Android

كتابة برنامج نصي للعمل مع قاعدة البيانات


وأخيراً ، يمكننا البدء في كتابة برنامج نصي للعمل مع قاعدة البيانات التي تم إنشاؤها. أولاً ، قم بإنشاء ملف MyDataBase وتوصيل مكتبات System.Data و Mono.Data.Sqlite و System.IO ، وجعل فئة MyDataBase ثابتة ، وبطبيعة الحال ، قم بإزالة الوراثة من MonoBehaviour. إضافة 3 متغيرات خاصة وثابتة مع اسم ملف قاعدة البيانات. يجب أن نحصل على شيء مثل هذا:

 using UnityEngine; using System.Data; using Mono.Data.Sqlite; using System.IO; static class MyDataBase { private const string fileName = "db.bytes"; private static string DBPath; private static SqliteConnection connection; private static SqliteCommand command; } 

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

 static MyDataBase() { DBPath = GetDatabasePath(); } /// <summary>    .        ,      apk . </summary> private static string GetDatabasePath() { #if UNITY_EDITOR return Path.Combine(Application.streamingAssetsPath, fileName); #if UNITY_STANDALONE string filePath = Path.Combine(Application.dataPath, fileName); if(!File.Exists(filePath)) UnpackDatabase(filePath); return filePath; #elif UNITY_ANDROID string filePath = Path.Combine(Application.persistentDataPath, fileName); if(!File.Exists(filePath)) UnpackDatabase(filePath); return filePath; #endif } /// <summary>      . </summary> /// <param name="toPath">       . </param> private static void UnpackDatabase(string toPath) { string fromPath = Path.Combine(Application.streamingAssetsPath, fileName); WWW reader = new WWW(fromPath); while (!reader.isDone) { } File.WriteAllBytes(toPath, reader.bytes); } 

المذكرة. نحتاج إلى فك حزم قاعدة البيانات في المسارات المحددة ( Application.dataPath / db.bytes لنظامي التشغيل Windows و Application.persistentDataPath / db.bytes لنظام Android) لأن مجلد StreamingAssets ، بعد التجميع ، له سمة ReadOnly (باستثناء نظام Android) ولن نتمكن من كتابة أي شيء ثم في قاعدة البيانات. في الواقع ، لكي نتمكن من كتابة شيء ما في قاعدة البيانات ، نقوم بفك ضغط قاعدة البيانات الخاصة بنا. يقال بالتفصيل الطرق التي ، بموجبها منصة لاستخدامها في هذه المقالة .

سنقوم بكتابة طرق لفتح الاتصال وإغلاقه ، وكذلك الطريقة التي ستنفذ طلبًا لا يتطلب إرجاع القيم ، على سبيل المثال ، INSERT و UPDATE و CREATE و DELETE و DROP.

 /// <summary>      . </summary> private static void OpenConnection() { connection = new SqliteConnection("Data Source=" + DBPath); command = new SqliteCommand(connection); connection.Open(); } /// <summary>      . </summary> public static void CloseConnection() { connection.Close(); command.Dispose(); } /// <summary>     query. </summary> /// <param name="query">  . </param> public static void ExecuteQueryWithoutAnswer(string query) { OpenConnection(); command.CommandText = query; command.ExecuteNonQuery(); CloseConnection(); } 

بأعجوبة ، الآن يمكن للبرنامج النصي تنفيذ طلبات تعديل البيانات. ولكن ماذا عن اختيار مهم جدا؟ قررت أن قيمة الإرجاع للأسلوب الذي يجب أن ينفذ استعلام اختيار البيانات يجب أن تكون من النوع أو السلسلة DataTable ، إذا كنت ترغب في الحصول على قيمة واحدة. للقيام بذلك ، اكتب طريقتين:

 /// <summary>     query    . </summary> /// <param name="query">  . </param> /// <returns>   1  1 ,   . </returns> public static string ExecuteQueryWithAnswer(string query) { OpenConnection(); command.CommandText = query; var answer = command.ExecuteScalar(); CloseConnection(); if (answer != null) return answer.ToString(); else return null; } /// <summary>    ,      query. </summary> /// <param name="query">  . </param> public static DataTable GetTable(string query) { OpenConnection(); SqliteDataAdapter adapter = new SqliteDataAdapter(query, connection); DataSet DS = new DataSet(); adapter.Fill(DS); adapter.Dispose(); CloseConnection(); return DS.Tables[0]; } 

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

 using System.Collections; using System.Collections.Generic; using System.Data; using UnityEngine; public class ScoreManager : MonoBehaviour { private void Start() { //     DataTable scoreboard = MyDataBase.GetTable("SELECT * FROM Scores ORDER BY score DESC;"); //  id   int idBestPlayer = int.Parse(scoreboard.Rows[0][1].ToString()); //     string nickname = MyDataBase.ExecuteQueryWithAnswer($"SELECT nickname FROM Player WHERE id_player = {idBestPlayer};"); Debug.Log($"  {nickname}  {scoreboard.Rows[0][2].ToString()} ."); } } 

إليك ما نحصل عليه عند بدء التشغيل:



شكرا لك على اهتمامك ، وسأقبل بكل سرور النقد البناء.

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


All Articles