در مطلب های پیشین روش ایجاد یک تک کلاس موجودیت را توضیح دادیم که به یک تک جدول اشاره می کند. همچنین LINQ برای انجام کوئری روی آن نیز آموزش داده شده است. در محیط واقعی، چندین جدول وجود دارند که میان برخی از آنها رابطه وجود دارد که کوئری های پیچیده تری مانند Join و Union را می توانیم روی آنها انجام دهیم. در این مطلب و چندین مطلب پیش رو، می خواهیم در مورد ایجاد کلاس های موجودیتی صحبت کنیم که درون بدنه خود، رابطه یک به چند و چند به چند را نیز تعریف می کنند.

در مطلب های زیر توضیح دادیم که میان دو موجودیت می تواند رابطه یک به یک (One-to-One) یا یک به چند (One-to-Many) یا چند به چند (Many-to-Many) وجود دارد و لازم است این رابطه در تعریف کلاس های موجودیت نیز وجود داشته باشد. در پایگاه داده های رابطه ای از کلید خارجی، برای ارتباط دادن یک جدول به جدول دیگر استفاده می شود. در یک جدول، کلید خارجی، ستونی است که در جدول مرتبط به عنوان کلید اصلی است.

انواع رابطه میان جدول ها در پایگاه داده رابطه ای

مثال انواع رابطه میان جدول ها

به طور مثال در رابطه میان مشتری و سفارش، هر مشتری می تواند چندین سفارش داشته باشد ولی هر سفارش مربوط به یک مشتری است، بنابراین در این حالت یک رابطه یک به چند وجود دارد. در این نوع رابطه، کلید خارجی درون جدول سفارش قرار می گیرد، زیرا می خواهیم به ازای هر سفارش، سفارش دهنده (مشتری) را نیز پیدا کنیم. بنابراین کلید خارجی باید در جدولی باشد که در سمت چند (Many) از رابطه وجود دارد که در نمونه گفته شده، چون چندین سفارش وجود دارد، پس کلید خارجی در جدول سفارش ایجاد می شود که به کلید اصلی در جدول مشتری اشاره می کند.

در رابطه چند به چند، چون هر دو سمت به صورت Many (چندین) هستند، پس نمی توانیم در هر دو جدول کلید خارجی ایجاد کنیم. در رابطه چند به چند باید یک جدول میانی (Pivot Table) ایجاد کنیم که باید دارای دو ستون به عنوان کلید خارجی دو جدول مرتبط به هم باشد. به طور مثال در رابطه میان استاد و دانشجو، در هر نیم سال، هر دانشجو می تواند چندین استاد و هر استاد نیز می تواند چندین دانشجو داشته باشد، پس نوع رابطه چند به چند است. در این حالت سه جدول استاد، دانشجو و جدول میانی را خواهیم داشت که جدول میانی شامل دو کلید خارجی برای دو جدول استاد و دانشجو است. البته جدول میانی که آنرا جدول الحاق (Join Table) نیز می گویند، می تواند ستون های بیشتری داشته باشد ولی در حالت کمینه باید دارای دو ستون به عنوان کلیدهای خارجی برای دو جدول دیگر داشته باشد.

در Entity Framework ارتباط میان دو موجودیت را توسط Association نشان داده می شود که هر Association دارای دو سمت است که هر سمت نوع و چندگانگی (هیچ، هیچ یا یکی یا چندین) را نشان می دهد. به طور نمونه در رابطه میان مشتری و سفارش، ممکن است مشتری هنوز سفارشی نداشته باشد، یا می تواند یک تا چندین سفارش داشته باشد. در شکل زیر که مربوط به نمودار طراحی شده توسط EF Designer است، می توانید مثالی از رابطه یک به چند میان دو جدول دپارتمان و دوره را ببینید که در هر دپارتمان دارای چندین دوره ولی هر دوره متعلق به یک دپارتمان است.

در شکل بالا و زمانی که میان دو موجودیت رابطه ای وجود داشته باشد، یک بخش به نام Navigation Properties به وجود می آید که در آن رابطه های (Association) میان دو موجودیت فهرست شده اند. همانطور که می بینید، DepartmentId (قاعده نامگذاری کلید های اصلی) به عنوان کلید اصلی در موجودیت Department است و چون به ازای هر دپارتمان چندین دوره وجود دارد، پس ستون DepartmentId در موجودیت Course به عنوان کلید خارجی به موجودیت Department است. بنابراین Navigation Property مفهومی است که ارتباط میان دو موجودیت را نشان می دهد.

تعریف رابطه یک به چند در کلاس های موجودیت

ابتدا یک پروژه کنسولی ایجاد و سپس مطابق آموزش های پیشین Entity Framework را نصب کنید. سپس دو فایل کلاس سی شارپ (پسوند cs) یکی برای کلاس Department و یک فایل برای کلاس Course تعریف کنید. همچنین می توانید یک فایل به نام مثلا Models.cs ایجاد کرده و سپس هر دو کلاس را درون همین فایل فایل تعریف کنید. چیزی که مهم است اینکه این دو کلاس و کلاس دیگر، یعنی کلاس Context در یک فضای نام قرار دارند. همچنین لازم است تا یک LocalDB ایجاد و سپس بخش ConnectionSettings در فایل App.Config را ایجاد و با پارامترها و مقدارهای مناسب تنظیم کنید.

در کد های شکل های زیر دو کلاس به نام Department و Course برای دو موجودیت شکل بالا ایجاد شده اند. در کلاس Course چون باید کلید خارجی به جدول Department تعریف کنیم، پس خصوصیت Department به صورت مجازی (Virtual) از نوع کلاس Department تعریف شده است. در پایین و در کلاس Department چون هر دپارتمان می تواند دارای چندین دوره باشد، پس نیاز داریم مجوعه ای از اشیا (Collection of Objects) کلاس دوره را داشته باشیم. یک Collection شامل مجموعه ای (یا گروهی) از اشیا است که در این مثال Collection تعریف شده درون کلاس Department شامل گروهی از اشیا کلاس Course است که بازهم به صورت مجازی تعریف شده است.

قاعده های تازه در مورد رابطه یک به چند

قاعده ۸ – برای ایجاد رابطه یک به چند و برای ایجاد کلید خارجی درون جدولی که در سمت چند (Many) وجود دارد، باید در کلاس سمت چند، یک کلید خارجی را به صورت یک خصوصیت مجازی از نوع کلاس سمت دیگر تعریف کرد. بنابراین در کلاس دوره (هر دپارتمان چندین دوره دارد)، یک خصوصیت مجازی از نوع کلاس Department (کلید خارجی به جدول Department) تعریف شده است.

قاعده ۹ – در سمت کلاس دیگر باید یک خصوصیت Collection از نوع کلاس سمت Many ایجاد شود تا نشان دهیم به ازای کلاس چندین نمونه از شی کلاس دیگر وجود دارد. بنابراین در کلاس دپارتمان چون چندین دوره وجود دارد، پس Collection از نوع کلاس Course تعریف شده است.

پس از تعریف کلاس های موجودیت (Entity Class)، باید کلاس دیگری، یعنی کلاس Context را تعریف کنیم که این بار دارای دو خصوصیت Dbset است که یکی به کلاس Department و دیگری به کلاس Course اشاره دارند. توجه کنید که این فایل و فایل های مربوط به کلاس های Department و Course همگی در یک فضای نام قرار دارند. بنابراین اگر هم اکنون برنامه را اجرا کنید، دو جدول به ساختار زیر درون پایگاه داده LocalDB ایجاد می شوند.

پس از آن مطابق کدهای زیر و درون فایل Program.cs می توانیم رکوردهایی را درون جدول ها درج کنیم. ابتدا می توانیم چندین دوره را یا اینکه ابتدا یک دپارتمان را تعریف کنیم. به هر حال طبق مطلب های پیشین ابتدا شی از کلاس Context درون عبارت using ایجاد شده و سپس درون بدنه آن و در مثال کد زیر سه شی به ترتیب اولی برای دپارتمان و دو تای دیگر برای کلاس دوره ایجاد شده اند.

پس از آن  در خط های – و – شی های course1 و course2 را به ترتیب توسط فرمان های department.Courses.Add(course1) و department.Courses.Add(course1) را به شی department اضافه کردیم زیرا هر دپارتمان می تواند تا چندین دوره داشته باشد. سپس در خط و این بار توسط شی context خود شی department را به پایگاه داده اعمال می کنیم. در واقع با این کار کوئری آماده می شود که شامل داده های دپارتمان است که بخشی از داده های دپارتمان شامل داده های خود دپارتمان و داده های مربوط به دوره آن می شود. در نهایت نیز متد ()SaveChanges برای اعمال تغییرات فراخوانی شده است.