0Pricing
C# Academy · درس

العلاقات: واحد إلى متعدد ومتعدد إلى متعدد

نمذجوا العلاقات واحد إلى متعدد ومتعدد إلى متعدد واستعلموا عنها باستخدام خصائص التنقّل وFluent API.

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

العلاقات في EF Core

تنمذج EF Core ثلاثة أنواع من العلاقات بين الكيانات: واحد إلى واحد، وواحد إلى متعدد، ومتعدد إلى متعدد. ويُعبَّر عن كل نوع باستخدام خصائص التنقّل، ويمكن تهيئته اختياريًا باستخدام Fluent API.

واحد إلى متعدد: إعداد الكيانات

يمتلك Blog العديد من Posts. ويحتوي الكيان التابع (Post) على المفتاح الخارجي. وتسمح خصائص التنقّل على الجانبين بالتنقّل في كلا الاتجاهين.

public class Blog
{
    public int Id { get; set; }
    public string Name { get; set; } = "";
    public ICollection<Post> Posts { get; set; } = new List<Post>();
}

public class Post
{
    public int Id { get; set; }
    public string Title { get; set; } = "";
    public int BlogId { get; set; }        // FK
    public Blog Blog { get; set; } = null!; // nav property
}

Fluent API: علاقة واحد إلى متعدد

تستنتج EF Core العلاقة وفقًا للاتفاقيات، ولكن يمكنك تحديدها صراحةً باستخدام Fluent API لمزيد من الوضوح ولضبط سلوك الحذف المتسلسل.

protected override void OnModelCreating(ModelBuilder mb)
{
    mb.Entity<Blog>()
      .HasMany(b => b.Posts)
      .WithOne(p => p.Blog)
      .HasForeignKey(p => p.BlogId)
      .OnDelete(DeleteBehavior.Cascade);
}

الاستعلام باستخدام Include (التحميل المبكر)

استخدم Include لتحميل البيانات المرتبطة ضمن الاستعلام نفسه. واستخدم ThenInclude للتعمّق أكثر في مخطط التنقّل.

// Load blog with all its posts
var blog = await _db.Blogs
    .Include(b => b.Posts)
    .FirstOrDefaultAsync(b => b.Id == 1);

// Load posts with their comments too
var blogs = await _db.Blogs
    .Include(b => b.Posts)
        .ThenInclude(p => p.Comments)
    .ToListAsync();

متعدد إلى متعدد دون كيان ربط

تدعم EF Core 5 والإصدارات الأحدث العلاقات من نوع متعدد إلى متعدد دون كيان ربط صريح. وتنشئ جدول الربط تلقائيًا باستخدام أسماء أنواع الكيانات.

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; } = "";
    public ICollection<Course> Courses { get; set; } = new List<Course>();
}

public class Course
{
    public int Id { get; set; }
    public string Title { get; set; } = "";
    public ICollection<Student> Students { get; set; } = new List<Student>();
}
// EF creates StudentCourse join table automatically

متعدد إلى متعدد مع كيان ربط

عندما يحتاج جدول الربط إلى أعمدة إضافية، مثل تاريخ التسجيل أو الدرجة، أنشئ كيان ربط صريحًا باستخدام مفتاح أساسي مركّب.

public class Enrollment
{
    public int StudentId { get; set; }
    public Student Student { get; set; } = null!;
    public int CourseId { get; set; }
    public Course Course { get; set; } = null!;
    public DateTime EnrolledAt { get; set; }
    public decimal? Grade { get; set; }
}

// Fluent API config:
mb.Entity<Enrollment>().HasKey(e => new { e.StudentId, e.CourseId });
mb.Entity<Enrollment>().HasOne(e => e.Student).WithMany(s => s.Enrollments);
mb.Entity<Enrollment>().HasOne(e => e.Course).WithMany(c => c.Enrollments);

إدراج البيانات المرتبطة

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

var blog = new Blog { Name = "Dev Notes" };
blog.Posts.Add(new Post { Title = "Hello EF Core" });
blog.Posts.Add(new Post { Title = "Migrations Deep Dive" });

_db.Blogs.Add(blog);
await _db.SaveChangesAsync();
// Inserts Blog + 2 Posts with correct BlogId FK

التصفية باستخدام البيانات المرتبطة

يمكنك إجراء التصفية باستخدام خصائص التنقّل في LINQ. وتحول EF Core هذه التصفية تلقائيًا إلى عبارات JOIN بلغة SQL.

// Blogs that have at least one published post
var popularBlogs = await _db.Blogs
    .Where(b => b.Posts.Any(p => p.IsPublished))
    .Select(b => new { b.Name, PostCount = b.Posts.Count(p => p.IsPublished) })
    .OrderByDescending(b => b.PostCount)
    .ToListAsync();

الحذف المتسلسل

مع استخدام DeleteBehavior.Cascade، يؤدي حذف الكيان الرئيسي (Blog) تلقائيًا إلى حذف جميع الكيانات التابعة (Posts). وتشمل الخيارات الأخرى: SetNull وRestrict وNoAction.

// Delete a blog and all its posts
var blog = await _db.Blogs.FindAsync(1);
_db.Blogs.Remove(blog!);
await _db.SaveChangesAsync();
// Cascade: all Posts with BlogId=1 are also deleted

الكيانات المملوكة لكائنات القيم

تُعد أنواع الكيانات المملوكة مناسبة جدًا لكائنات القيم، مثل Address. وتُخزَّن في الجدول نفسه الذي يُخزَّن فيه المالك، ولا تمتلك هوية مستقلة.

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; } = "";
    public Address ShippingAddress { get; set; } = new();
}

public class Address
{
    public string Street { get; set; } = "";
    public string City { get; set; } = "";
    public string Country { get; set; } = "";
}

// Fluent API:
mb.Entity<Customer>().OwnsOne(c => c.ShippingAddress);

تطبيق عملي: طلب مع عناصره

نمط متكامل للتجارة الإلكترونية: Order (الكيان الرئيسي) مع العديد من OrderLines (الكيانات التابعة)، حيث يشير كل منها إلى Product.

var order = await _db.Orders
    .Include(o => o.Lines)
        .ThenInclude(l => l.Product)
    .FirstOrDefaultAsync(o => o.Id == orderId);

if (order is null) return Results.NotFound();

var summary = new
{
    OrderId = order.Id,
    Total   = order.Lines.Sum(l => l.Quantity * l.Product.Price),
    Items   = order.Lines.Select(l => new
    {
        l.Product.Name,
        l.Quantity,
        LineTotal = l.Quantity * l.Product.Price
    })
};
return Results.Ok(summary);

اختبار سريع

متى تنشئ EF Core جدول ربط تلقائيًا دون كيان ربط صريح؟

مراجعة: العلاقات في EF Core

أهم النقاط:

  • واحد إلى متعدد: يوجد FK في الكيان التابع، وتوجد خاصية تنقّل على الجانبين، ويُستخدم Include للتحميل
  • متعدد إلى متعدد (بسيط): خاصيتا تنقّل من نوع ICollection — وتنشئ EF Core جدول الربط تلقائيًا
  • متعدد إلى متعدد (مع بيانات إضافية): كيان ربط صريح يحتوي على مفتاح أساسي مركّب
  • يتحكم الحذف المتسلسل فيما يحدث للكيانات التابعة عند إزالة الكيان الرئيسي
  • تنمذج الكيانات المملوكة كائنات القيم في الجدول نفسه الذي يُخزَّن فيه المالك

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

هل درس «العلاقات: واحد إلى متعدد ومتعدد إلى متعدد» مجاني؟

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

ماذا ستتعلم في «العلاقات: واحد إلى متعدد ومتعدد إلى متعدد»؟

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

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

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

كم من الوقت يستغرق درس «العلاقات: واحد إلى متعدد ومتعدد إلى متعدد»؟

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

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

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

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

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