0Pricing
C# Academy · درس

عمليات CRUD باستخدام EF Core

نفّذوا عمليات الإنشاء والقراءة والتحديث والحذف باستخدام تتبّع التغييرات في EF Core وSaveChanges.

عمليات CRUD باستخدام EF Core درس مجاني في C# Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C# Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C# Academy 4 دروس في المجموع.

نظرة عامة على CRUD في EF Core

تتعامل EF Core مع عمليات CRUD الأربع — الإنشاء والقراءة والتحديث والحذف — من خلال الجمع بين تتبّع التغييرات وSaveChangesAsync(). ويُعد فهم متعقّب التغييرات مفتاح إتقان CRUD.

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

استخدم DbSet.Add() أو AddAsync() لوضع الكيان في حالة Added. وعند استدعاء SaveChangesAsync()، تنشئ EF Core عبارة INSERT وتملأ المفتاح الذي يزداد تلقائيًا.

var order = new Order
{
    CustomerId = 5,
    PlacedAt   = DateTime.UtcNow,
    Status     = OrderStatus.Pending
};

await _db.Orders.AddAsync(order);
await _db.SaveChangesAsync();

Console.WriteLine(order.Id); // populated by DB

إضافة مجموعة من الكيانات المرتبطة

تؤدي إضافة كيان أب مع أبنائه في استدعاء واحد إلى إدراج مخطط الكائنات كاملًا. وتعالج EF Core علاقات FK تلقائيًا.

var order = new Order
{
    CustomerId = 5,
    PlacedAt   = DateTime.UtcNow,
    Lines      = new List<OrderLine>
    {
        new() { ProductId = 10, Quantity = 2, Price = 49.99m },
        new() { ProductId = 11, Quantity = 1, Price = 19.99m }
    }
};

_db.Orders.Add(order);
await _db.SaveChangesAsync();
// Inserts Order + 2 OrderLines in one transaction

القراءة: الاستعلام باستخدام LINQ

تحوّل EF Core تعبيرات LINQ إلى SQL. أنشئ الاستعلامات باستخدام Where وSelect وOrderBy وغير ذلك، ثم حوّل النتائج إلى كيانات باستخدام ToListAsync أو FirstOrDefaultAsync.

// Read all pending orders for a customer
var orders = await _db.Orders
    .Where(o => o.CustomerId == 5 && o.Status == OrderStatus.Pending)
    .OrderByDescending(o => o.PlacedAt)
    .Select(o => new OrderSummaryDto
    {
        Id     = o.Id,
        Total  = o.Lines.Sum(l => l.Quantity * l.Price),
        Status = o.Status.ToString()
    })
    .ToListAsync();

القراءة: البحث عن كيان واحد

لقراءة كيان واحد، استخدم FindAsync (إذ يتحقق أولًا من متعقّب التغييرات) أو استخدم FirstOrDefaultAsync / SingleOrDefaultAsync مع شرط.

// By PK (checks cache first)
var order = await _db.Orders.FindAsync(orderId);

// By predicate (always hits DB)
var latest = await _db.Orders
    .Where(o => o.CustomerId == 5)
    .OrderByDescending(o => o.PlacedAt)
    .FirstOrDefaultAsync();

التحديث: تتبّع التغييرات

تتتبّع EF Core الكيانات التي تحمّلها. عدّل الخصائص مباشرةً ثم استدعِ SaveChangesAsync(). تكتشف EF Core الفرق وتنشئ عبارة UPDATE مقتصرة على التغييرات.

var order = await _db.Orders.FindAsync(orderId);
if (order is null) return;

order.Status   = OrderStatus.Shipped;
order.ShippedAt = DateTime.UtcNow;

await _db.SaveChangesAsync();
// UPDATE Orders SET Status=..., ShippedAt=... WHERE Id=orderId

التحديث: تحديث دفعي (EF Core 7 والإصدارات الأحدث)

يحدّث ExecuteUpdateAsync الصفوف مباشرةً في قاعدة البيانات دون تحميل الكيانات. ويكون ذلك أكثر كفاءة بكثير في العمليات الدفعية.

// Mark all overdue orders as Cancelled — no loading needed
await _db.Orders
    .Where(o => o.Status == OrderStatus.Pending
             && o.PlacedAt < DateTime.UtcNow.AddDays(-30))
    .ExecuteUpdateAsync(set => set
        .SetProperty(o => o.Status, OrderStatus.Cancelled)
        .SetProperty(o => o.UpdatedAt, DateTime.UtcNow));

الحذف: إزالة كيان واحد

استدعِ Remove() على كيان تتمتّع EF Core بتتبّعه، ثم استدعِ SaveChangesAsync(). وإذا لم يكن لديك سوى المعرّف، فابحث عن الكيان أولًا أو استخدم ExecuteDeleteAsync.

var order = await _db.Orders.FindAsync(orderId);
if (order is null) return;

_db.Orders.Remove(order);
await _db.SaveChangesAsync();
// DELETE FROM Orders WHERE Id=orderId

الحذف: حذف دفعي (EF Core 7 والإصدارات الأحدث)

ينفّذ ExecuteDeleteAsync عبارة DELETE واحدة بلغة SQL دون تحميل الكيانات، ولذلك فهو مناسب لعمليات التنظيف الدفعية.

// Delete all cancelled orders older than 1 year
int deleted = await _db.Orders
    .Where(o => o.Status == OrderStatus.Cancelled
             && o.PlacedAt < DateTime.UtcNow.AddYears(-1))
    .ExecuteDeleteAsync();

Console.WriteLine($"Deleted {deleted} old orders");

المعاملات

تُغلَّف جميع العمليات داخل استدعاء واحد لـ SaveChangesAsync ضمن معاملة. أما العمليات متعددة الخطوات التي تمتد عبر عمليات حفظ متعددة، فاستخدم لها معاملة صريحة.

using var transaction = await _db.Database.BeginTransactionAsync();
try
{
    _db.Orders.Add(newOrder);
    await _db.SaveChangesAsync();

    inventory.Stock -= newOrder.Quantity;
    await _db.SaveChangesAsync();

    await transaction.CommitAsync();
}
catch
{
    await transaction.RollbackAsync();
    throw;
}

تطبيق عملي: خدمة CRUD كاملة

تغلّف الخدمة الكاملة جميع عمليات CRUD مع معالجة مناسبة للأخطاء، وتعيد DTOs لتجنّب كشف التفاصيل الداخلية للكيانات.

public async Task<OrderDto> CreateOrderAsync(CreateOrderRequest req)
{
    var order = new Order { CustomerId = req.CustomerId, PlacedAt = DateTime.UtcNow };
    _db.Orders.Add(order);
    await _db.SaveChangesAsync();
    return new OrderDto { Id = order.Id, Status = order.Status.ToString() };
}

public async Task<bool> CancelOrderAsync(int id)
{
    int rows = await _db.Orders
        .Where(o => o.Id == id && o.Status == OrderStatus.Pending)
        .ExecuteUpdateAsync(s =>
            s.SetProperty(o => o.Status, OrderStatus.Cancelled));
    return rows > 0;
}

اختبار سريع

ما ميزة ExecuteUpdateAsync / ExecuteDeleteAsync مقارنةً بتحميل الكيانات ثم استدعاء SaveChangesAsync؟

مراجعة: عمليات CRUD باستخدام EF Core

أهم النقاط:

  • Add + SaveChangesAsync → INSERT؛ وتملأ EF Core المفاتيح المُنشأة تلقائيًا
  • تعديل الكيانات التي تتمتّع EF Core بتتبّعها + SaveChangesAsync → UPDATE مقتصر على التغييرات
  • Remove + SaveChangesAsync → DELETE للكيانات المفردة
  • ExecuteUpdateAsync / ExecuteDeleteAsync → عمليات دفعية دون تحميل الكيانات (في EF Core 7 والإصدارات الأحدث)
  • غلّف العمليات متعددة الخطوات ضمن معاملة صريحة لضمان تنفيذها كوحدة ذرّية

الأسئلة الشائعة

هل درس «عمليات CRUD باستخدام EF Core» مجاني؟

نعم — نص درس «عمليات CRUD باستخدام EF Core» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C# Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C# Academy 4 دروس في المجموع.

ماذا ستتعلم في «عمليات CRUD باستخدام EF Core»؟

نفّذوا عمليات الإنشاء والقراءة والتحديث والحذف باستخدام تتبّع التغييرات في EF Core وSaveChanges. تتمرن على C# Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ C# Academy؟

لا تُشترط خبرة سابقة. C# Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «عمليات CRUD باستخدام EF Core»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس C# Academy هذا؟

نعم. كل درس في C# Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. أساسيات DbContext وDbSet
  2. عمليات الترحيل وإدارة المخطط
  3. عمليات CRUD باستخدام EF Core
  4. العلاقات: واحد إلى متعدد ومتعدد إلى متعدد
← العودة إلى C# Academy