تخزين البيانات محليًا باستخدام SQLite

مكتمل

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

في هذه الوحدة، ستتعلم كيفية استخدام SQLite في تطبيق .NET MAUI باستخدام SQLite-net.

ما SQLite؟

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

يتم تضمين مكتبات SQLite الأصلية في Android وiOS بشكل افتراضي؛ ومع ذلك، يدعم المحرك واجهة برمجة تطبيقات C/C++ فقط. هذا السيناريو ليس مثالياً لمطوري .NET، الذين يريدون طريقة معينة لتفاعل SQLite و.NET.

ما هو SQLite-net؟

هناك عدة برامج تضمين C# حول محرك SQLite الأصلي الذي يمكن لمطوري .NET استخدامه. يستخدم العديد من مطوري .NET برنامج تضمين C# شائع يسمى SQLite-net.

SQLite-net هو مخطط كائن علائقي. يساعد على تبسيط عملية تعريف مخططات قاعدة البيانات من خلال السماح لك باستخدام النماذج المحددة في مشاريعك لتكون بمثابة المخطط.

Diagram showing how SQLite-net provides a .NET wrapper and the SQLite C/C++ engine.

على سبيل المثال، ضع في اعتبارك الفئة التالية التي تنمذج User:

class User
{
    public int Id { get; set; }
    public string Username { get; set; }
    ...
}

باستخدام معين كائن علائقي، يمكنك أخذ هذه الفئة الأولية User وإنشاء جدول قاعدة بيانات يسمى User يحتوي على أعمدة للحولتين Id و Username في هذه الفئة.

يتم شحن SQLite-net كحزمة NuGet. يجب إضافة حزمة sqlite-net-pcl إلى تطبيقاتك لاستخدامها. استخدم مدير حزمة NuGet في Visual Studio. بالإضافة إلى ذلك، إذا كنت ترغب في تشغيل تطبيق على Android، فيجب عليك أيضا إضافة حزمة SQLitePCLRaw.provider.dynamic_cdecl .

كيفية الاتصال بقاعدة بيانات SQLite

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

تعرض التعليمات البرمجية التالية مثالاً.

using SQLite;
...
string filename = ...
SQLiteConnection conn = new SQLiteConnection(filename);

تذكر أنه يجب أن filename يشير إلى موقع في بيئة الاختبار المعزولة للتطبيق.

كيفية إنشاء جدول

تذكر أن SQLite-net هو معين كائن علائقي، ما يعني أنه يمكنك إنشاء مخطط قاعدة البيانات من فئات C#. يمكن ل SQLite-net إنشاء جدول قاعدة بيانات من فئة C# عادية، ولكن هناك العديد من السمات التي يمكنك إضافتها إلى فئة لتوفير بيانات تعريف إضافية. تساعد بيانات التعريف هذه SQLite على فرض ميزات مثل التفرد وتطبيق القيود على بياناتك.

تتضمن السمات المتوفرة ما يلي:

  • Table: حدد اسم الجدول إذا كنت تريد أن يكون شيئا آخر غير اسم الفئة
  • PrimaryKey: حدد أن العمود هو المفتاح الأساسي
  • AutoIncrement: حدد أن العمود يجب أن يزيد تلقائيا في القيمة عند إدراج صف جديد
  • Column: حدد اسم عمود إذا كنت تريد أن يكون شيئا آخر غير اسم الخاصية
  • MaxLength: حدد الحد الأقصى لعدد الأحرف التي يمكن استخدامها في العمود
  • Unique: حدد أن القيمة في العمود يجب أن تكون فريدة من جميع الصفوف الأخرى

تعرض التعليمات البرمجية التالية إصدارا محدثا من User الفئة التي تطبق هذه السمات:

[Table("user")]
public class User
{
    // PrimaryKey is typically numeric 
    [PrimaryKey, AutoIncrement, Column("_id")]
    public int Id { get; set; }

    [MaxLength(250), Unique]
    public string Username { get; set; }
    ...
}

بعد تعريف فئة C#، قم باستدعاء CreateTable الأسلوب العام على SQLiteConnection الفئة لإنشاء الجدول في قاعدة البيانات. حدد الفئة كمعلمة النوع. إليك مثال:

SQLiteConnection conn = new SQLiteConnection(filename);
conn.CreateTable<User>();

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

كيفية تنفيذ عمليات القراءة والكتابة الأساسية

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

public int AddNewUser(User user)
{
    int result = conn.Insert(user);
    return result;
}

يقوم Insert الأسلوب بإرجاع int، والذي يمثل عدد الصفوف المدرجة في الجدول. في هذه الحالة، يكون هذا العدد هو واحد.

لاسترداد صفوف من جدول، استخدم Table الأسلوب . يقوم هذا الأسلوب بإرجاع مجموعة من الكائنات (التي قد تكون فارغة):

public List<User> GetAllUsers()
{
    List<User> users = conn.Table<User>().ToList();
    return users;
}

تُعيد طريقة Table كائن TableQuery\<T>. للحصول على List، استخدم ToList الأسلوب كما هو موضح في المثال السابق.

تنفيذ استعلام SQLite باستخدام LINQ

يسترد Table الأسلوب كافة الصفوف من جدول. في معظم الحالات، تريد إرجاع مجموعة فرعية فقط من الصفوف التي تطابق مجموعة من المعايير المحددة. لهذه المهام، استخدم LINQ مع SQLite-net.

يدعم SQLite-net العديد من استعلامات LINQ الشائعة بما في ذلك:

  • الموقع
  • Take
  • ‏‏تخطي
  • OrderBy
  • ترتيب حسب الترتيب
  • ثم من خلال
  • عنصرAt
  • First
  • FirstOrDefault
  • ثم تصاعدي
  • عدد

باستخدام هذه الوسائل، يمكنك استخدام بنية أسلوب التوسيع أو بنية LINQ C#. على سبيل المثال، إليك مقتطف من التعليمات البرمجية التي تمكنك من استرداد تفاصيل مستخدم محدد:

public User GetByUsername(string username)
{
    var user = from u in conn.Table<User>()
               where u.Username == username
               select u;
    return user.FirstOrDefault();
}

تحديث الصفوف وحذفها

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

public int UpdateUser(User user)
{
    int result = 0;
    result = conn.Update(user);
    return result;
}

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

public int DeleteUser(int userID)
{
    int result = 0;
    result = conn.Delete<User>(userID);
    return result;
}