1. مقدمة حول عمليات الكائنات في ent
هذا الدليل سيوجّهك شاملًا نحو اتقان عمليات الكائنات في إطار ent
، حيث يشمل العملية الكاملة لإنشاء الكائنات، الاستعلام عنها، تحديثها، وحذفها. وهو مناسب للمبتدئين للانغماس تدريجيًا في الوظائف الأساسية لـ ent
.
3. عملية إنشاء الكائن
3.1 إنشاء كائن واحد
إنشاء الكائن هو العملية الأساسية لاستمرار البيانات. فيما يلي خطوات إنشاء كائن واحد باستخدام إطار ent
وحفظه في قاعدة البيانات:
- أولاً، قم بتعريف هيكل وحقول الكائن، أي قم بتعريف نموذج الكائن في ملف
المخطط
. - قم بتشغيل أمر
ent generate
لتوليد الكود الخاص بعمليات الكائن المقابلة. - استخدم الطريقة المولدة
Create
لبناء كائن جديد، وقم بتعيين قيم الحقول الخاصة بالكائن من خلال مكالمات متسلسلة. - وأخيرًا، استدعِ الطريقة
Save
لحفظ الكائن في قاعدة البيانات.
فيما يلي مثال يوضح كيفية إنشاء وحفظ كائن مستخدم:
package main
import (
"context"
"log"
"entdemo/ent"
)
func main() {
// إنشاء مثيل عميل لتفاعل مع قاعدة البيانات
client, err := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1")
if err != nil {
log.Fatalf("فشل في فتح اتصال قاعدة البيانات: %v", err)
}
defer client.Close()
// إنشاء سياق
ctx := context.Background()
// إنشاء كائن مستخدم باستخدام العميل
a8m, err := client.User.
إنشاء().
SetName("a8m").
Save(ctx)
if err != nil {
log.Fatalf("فشل في إنشاء كائن المستخدم: %v", err)
}
// تم حفظ الكائن بنجاح في قاعدة البيانات
log.Printf("كائن المستخدم تم حفظه: %v", a8m)
}
في هذا المثال، يتم إنشاء عميل لقاعدة بيانات client
أولاً. ثم، يتم استخدام الطريقة User.Create
لتعيين سمات المستخدم الجديد، وأخيرًا يتم استدعاء الطريقة Save
لحفظ المستخدم في قاعدة البيانات.
3.2 إنشاء كائن بالدُّفعة
في السيناريوهات المعيّنة، قد تكون هناك حاجة إلى إنشاء عدة كائنات، مثل أثناء تهيئة قاعدة البيانات أو عمليات استيراد البيانات بالجُملة. يوفّر إطار ent
إمكانية إنشاء كائنات بالدُّفعة، والتي توفر أداءً أفضل مقارنةً بإنشاء وحفظ الكائنات بشكل فردي.
تتمثل الخطوات لإنشاء كائن بالدُّفعة في:
- استخدام طريقة
CreateBulk
بدلاً من الطريقةCreate
، والتي تسمح بإنشاء عدة كائنات في عملية واحدة. - استدعاء
Create
لكل كائن يجب إنشاؤه. - بمجرد إنشاء جميع الكائنات، استخدم الطريقة
Save
لحفظ الكائنات في قاعدة البيانات بالجملة.
فيما يلي مثال عن إنشاء كائنات بالدُّفعة:
package main
import (
"context"
"log"
"entdemo/ent"
)
func main() {
client, err := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1")
if err != nil {
log.Fatalf("فشل في فتح اتصال قاعدة البيانات: %v", err)
}
defer client.Close()
ctx := context.Background()
// إنشاء كائنات Pet بالدُّفعة
pets, err := client.Pet.CreateBulk(
client.Pet.Create().SetName("pedro").SetOwner(a8m),
client.Pet.Create().SetName("xabi").SetOwner(a8m),
client.Pet.Create().SetName("layla").SetOwner(a8m),
).Save(ctx)
if err != nil {
log.Fatalf("فشل في إنشاء كائنات Pet بالدُّفعة: %v", err)
}
log.Printf("تم إنشاء %d كائن Pet بالدُّفعة\n", len(pets))
}
في هذا المثال، يتم إنشاء client
أولاً، ثم يتم بناء كائنات Pet
متعددة باستخدام الطريقة CreateBulk
، بتعيين أسمائهم وحقول المالك. يتم حفظ جميع الكائنات في قاعدة البيانات دفعة واحدة عند استدعاء الطريقة Save
، مما يوفر أداءً أفضل للتعامل مع كميات كبيرة من البيانات.
4. عمليات استعلام الكائنات
4.1 الاستعلام الأساسي
الاستعلام عن قاعدة البيانات هو الطريقة الأساسية لاسترجاع المعلومات. في ent
، يُستخدم الأسلوب Query
للبدء بالاستعلام. فيما يلي خطوات ومثال على الاستعلام الأساسي للكيانات:
- تأكد من وجود مثيل صالح لـ
Client
. - استخدم
Client.Query()
أو طرق مساعدة الكيان مثلPet.Query()
لإنشاء استعلام. - أضف شروط التصفية حسب الحاجة، مثل
Where
. - قم بتنفيذ الاستعلام واسترجاع النتائج عن طريق استدعاء الأسلوب
All
.
package main
import (
"context"
"log"
"entdemo/ent"
"entdemo/ent/user"
)
func main() {
client, err := ent.Open("sqlite3", "file:ent?cache=shared&_fk=1")
if err != nil {
log.Fatalf("فشل في فتح اتصال قاعدة البيانات: %v", err)
}
defer client.Close()
ctx := context.Background()
// الاستعلام عن جميع المستخدمين بالاسم "a8m"
users, err := client.User.
Query().
Where(user.NameEQ("a8m")).
All(ctx)
if err != nil {
log.Fatalf("فشل في استعلام المستخدمين: %v", err)
}
for _, u := range users {
log.Printf("تم العثور على المستخدم: %#v\n", u)
}
}
يوضح هذا المثال كيفية العثور على جميع المستخدمين بالاسم "a8m".
4.2 الترقيم والتصنيف
الترقيم والتصنيف هما ميزات متقدمة شائعة الاستخدام أثناء الاستعلام، وتستخدم للتحكم في ترتيب الإخراج وكمية البيانات. إليك كيفية تحقيق استعلامات الترقيم والتصنيف باستخدام ent
:
- استخدم الأسلوب
Limit
لتعيين الحد الأقصى لعدد النتائج المراد إرجاعها. - استخدم الأسلوب
Offset
لتخطي بعض النتائج السابقة. - استخدم الأسلوب
Order
لتحديد حقل التصنيف والاتجاه.
فيما يلي مثال على استعلام الترقيم والتصنيف:
package main
import (
"context"
"log"
"entdemo/ent"
"entdemo/ent/pet"
)
func main() {
client, err := ent.Open("sqlite3", "file:ent?cache=shared&_fk=1")
if err != nil {
log.Fatalf("فشل في فتح اتصال قاعدة البيانات: %v", err)
}
defer client.Close()
ctx := context.Background()
// الاستعلام عن الحيوانات الأليفة بترتيب تنازلي حسب العمر مع الترقيم
pets, err := client.Pet.
Query().
Order(ent.Desc(pet.FieldAge)).
Limit(10).
Offset(0).
All(ctx)
if err != nil {
log.Fatalf("فشل في استعلام الحيوانات الأليفة: %v", err)
}
for _, p := range pets {
log.Printf("تم العثور على الحيوان الأليف: %#v\n", p)
}
}
يوضح هذا المثال كيفية استرجاع الصفحة الأولى، ما يصل إلى 10 سجلات، للحيوانات الأليفة مرتبة تنازليًا حسب العمر. يمكنك بتعديل قيم Limit
و Offset
تحقيق الإنتقال عبر مجموعة البيانات بأكملها.
5. عمليات تحديث الكيان
5.1 تحديث كيان واحد
في العديد من التطبيقات، تحديث الكيانات هو جزء أساسي من العمليات اليومية. في هذا القسم، سنقوم بشرح كيفية استخدام إطار العمل Ent لتحديث كيان واحد في قاعدة البيانات.
أولاً، افتراضًا أنه نحتاج لتحديث عمر مستخدم، يمكننا الاستفادة من الأسلوب Update
الذي يتم إنشاؤه بواسطة Ent.
// افترضنا أن لدينا بالفعل كيان مستخدم 'a8m' وسياق 'ctx'
a8m, err := a8m.Update(). // إنشاء بناء تحديث مستخدم
SetAge(30). // تعيين عمر المستخدم إلى 30 عامًا
Save(ctx) // القيام بعملية الحفظ واسترجاع النتيجة
if err != nil {
log.Fatalf("فشل في تحديث المستخدم: %v", err)
}
يمكنك أيضًا تحديث عدة حقول بشكل متزامن:
a8m, err := a8m.Update().
SetAge(30). // تحديث العمر
SetName("أرييل"). // تحديث الاسم
AddRank(10). // زيادة الترتيب بمقدار 10
Save(ctx)
if err != nil {
log.Fatalf("فشل في تحديث المستخدم: %v", err)
}
يمكن ربط العملية التحديث، وهي مرنة للغاية وسهلة القراءة. سيقوم استدعاء الأسلوب Save
بإجراء التحديث واسترجاع الكيان المحدث أو رسالة الخطأ.
5.2 التحديثات الشرطية
يتيح Ent لك أداء التحديثات استنادًا إلى الشروط. إليك مثالًا حيث سيتم تحديث المستخدمين الذين يستوفون شروطًا معينة فقط.
// نفترض أن لدينا `id` لمستخدم ونريد وضع علامة لهذا المستخدم كمكتمل للإصدار `currentVersion`
err := client.Todo.
UpdateOneID(id). // إنشاء بنّاء للتحديث بواسطة معرف المستخدم
SetStatus(todo.StatusDone).
AddVersion(1).
Where(
todo.Version(currentVersion), // يتم تنفيذ عملية التحديث فقط عندما يتطابق الإصدار الحالي
).
Exec(ctx)
switch {
case ent.IsNotFound(err):
fmt.Println("المهمة غير موجودة")
case err != nil:
fmt.Println("خطأ في التحديث:", err)
}
عند استخدام التحديثات الشرطية، يجب أن يُشارك في استخدام الأسلوب .Where()
، حيث يسمح لك بتحديد ما إذا كان يجب تنفيذ التحديث بناءً على القيم الحالية في قاعدة البيانات، مما يعد أمرًا حاسمًا لضمان استمرارية البيانات وسلامتها.
6. عمليات حذف الكيانات
6.1 حذف كيان واحد
حذف الكيانات هو وظيفة مهمة أخرى في عمليات قواعد البيانات. يوفر إطار العمل Ent واجهة برمجة بسيطة لأداء عمليات الحذف.
يوضح المثال التالي كيفية حذف كيان مستخدم معين:
err := client.User.
DeleteOne(a8m). // إنشاء بنّاء حذف مستخدم
Exec(ctx) // تنفيذ عملية الحذف
if err != nil {
log.Fatalf("فشل في حذف المستخدم: %v", err)
}
6.2 حذف شرطي
بالمثل لعمليات التحديث، يمكننا أيضًا أداء عمليات الحذف استنادًا إلى شروط معينة. في بعض السيناريوهات، قد نرغب في حذف الكيانات التي تستوفي شروطًا محددة فقط. يمكن استخدام الأسلوب .Where()
لتحديد هذه الشروط:
// نفترض أننا نريد حذف كافة الملفات بوقت تحديث سابق لتاريخ معين
affected, err := client.File.
Delete().
Where(file.UpdatedAtLT(date)). // تنفيذ الحذف فقط إذا كان وقت تحديث الملف سابقًا للتاريخ المعطى
Exec(ctx)
if err != nil {
log.Fatalf("فشل في حذف الملفات: %v", err)
}
// تقوم هذه العملية بإرجاع عدد السجلات التي تأثرت بها عملية الحذف
fmt.Printf("%d ملف تم حذفه\n", affected)
استخدام عمليات الحذف الشرطية يضمن السيطرة الدقيقة على عمليات البيانات الخاصة بنا، مضمونًا أنه يتم حذف الكيانات التي تستوفي حقًا الشروط. وهذا يعزز أمان وموثوقية عمليات قاعدة البيانات.