خانه > DataBase, Programming, معرفی > پیاده سازی و پیکربندی NHibernate (با یک نمونه)

پیاده سازی و پیکربندی NHibernate (با یک نمونه)

در مطالب قبلی با مفهوم و کارایی ORMapper آشنا شدیم و سپس به معرفی NHibernate پرداختیم، در این مطلب قصد داریم تا با استفاده از یک مثال، بطور عملی یک پروژه را توسط NHibernate به Database پیوند دهیم. پس از انجام مراحل زیر شما بصورت عملی یک سیستم را با استفاده از NHibernate پیاده‌سازی کرده‌اید. لازم بذکر است که این مثال از سایت theserverside.net اقتباس شده است که با استفاده از این لینک می‌توانید اصل مطلب را ملاحظه کنید.
تمرین شماره یک : پیاده‌سازی عملی NHibernate

اهداف:

1. ایجاد فایل mapper

2. مشخص کردن primary key و identifier ها در فایل‌های مپر
3. ایجاد رابطه یک به چند در فایل‌های مپر ان.هایبرنیت
4. ایجاد رابطه چند به چند در فایل‌های مپر ان.هایبرنیت
5. ایجاد زیرکلاس در فایل‌های مپر
این مثال شامل یک سیستم داشجویی است که دربرگیرنده بخش‌های زیر است:
Department
University
Professor
Student

که ارتباطاتشان به صورت زیر تعریف شده است :

تمرین یک : روابط بین کلاس‌ها

تمرین یک : روابط بین کلاس‌ها

توضیحات :
یک دانشگاه دارای یک یا چند استاد است و یک استاد در یک یا چند دانشگاه مشغول به کار است، یک دانشگاه یک یا چند کلاس دارد و کلاس‌ها متعلق به یک دانشگاه هستند ، کلاس را یک استاد اداره می‌کند و هر استاد می‌تواند چند کلاس را اداره کند ، دانشجویان می‌توانند یک یا چند کلاس داشته باشند و هر کلاس می‌تواند یک یا چند دانشجو داشته باشد .
تعریف کلاس‌ها به صورت زیر می‌باشد :

public class Department
{
private int id;
private string name;
private IDictionary classes;
private IDictionary professors;
}
public class Professor : Person
{
private int id;
private string firstname;
private string lastname;
private string id;
private IDictionary departments;
private IDictionary classes;
}

public class UniversityClass
{
private int id;
private string name;
private string number;
private string syllabus;
private DateTime startDate;
private Professor professor;
private IDictionary students;
private Department department;
}

public class Student : Person
{
private int id;
private string firstname;
private string lastname;
private string ssn;
private IDictionary classes;
}

public interface Person
{
public int Id;
public string FirstName;
public string LastName;
}

و نهایتا ساختار Database بدین شکل خواهد بود:
تمرین یک : روابط بین جداول پایگاه داده

تمرین یک : روابط بین جداول پایگاه داده

فایل‌های map شده

مرحلهٔ بعد فراهم کردن فایل‌های مپ شده است که با اطلاعات موجود در جداول در ارتباط هستند. هر کلاس، فایل‌های مپ شدهٔ خود را نیاز دارد. این فایل‌ها می‌توانند هرجا که شما بخواهید ذخیره شوند. اما بهتر است برای سادگی کار یک library به پروژه add کنید و این فایل‌ها را در آنجا ذخیره کنید. توجه داشته باشید که فایل‌های مپ شده برای ویژگی‌هایی که قرار است ماندگار (Persistence) باشند (ذخیره شوند) تهیه می‌شوند.

گام نخست: ایجاد جداول در پایگاه داده
برای شروع کار ابتدا در DataBase، جداول مربوطه را تشکیل می‌دهیم. (درست مانند شکل بالا، به این معنی که باتوجه به تصویر جداول پایگاه داده، این جداول را در Database ایجاد کنید).
گام دوم: ایجاد فایل‌های Map
س‍پس اقدام به ایجاد فایل‌های مپ شده می‌کنیم. (توجه داشده باشید که این کلاس‌ها باید با پسوند .xml ذخیره شوند). برای مثال باتوجه به موارد بالا، اگر بخواهیم برای کلاس Department فایل مپ ایجاد کنیم، باید بصورت زیر عمل کنیم. بدین منظور ابتدا تگ شناسایی xml را در ابتدای فایل بصورت زیر قرار می‌دهیم.

<?xml version=«1.0« encoding=«utf-8« ?>

بعد باید مشخص کنیم که این فایل یک فایل مپ شده برای NHibernate است. بدین منظور به شکل زیر NameSpace مورد استفاده را به فایل اضافه می‌کنیم.
<!–[if gte mso 9]> Normal 0 false false false EN-US X-NONE AR-SA <![endif]–><!–[if gte mso 9]> <![endif]–>

<hibernate-mapping xmlns=«urn:nhibernate-mapping-2.0«>

حالا برای mapping مراحل زیر را طی می‌کنیم:
در ابتدا مشخص می‌کنیم که کدام کلاس را مپ می‌کنیم. این کار را با نوشتن کلمهٔ class و نسبت دادن یک نام به آن انجام می‌دهیم.

<!–[if gte mso 9]> Normal 0 false false false EN-US X-NONE AR-SA <![endif]–><!–[if gte mso 9]> <![endif]–> <!–[endif]–>

<class name=«nhRegistration.Department, nhRegistration» table=«Department« />

حالا مشخصه‌ها را به یک فیلد DataBase مپ می‌کنیم. برای این کار باید نام مشخصه، ستون و نوع آن بیان شود. توجه داشته باشید که مقدار name در برنامه قابل دسترسی است و مقدار column باید و باید مشابه نام ستونی باشد که در جدول پایگاه داده ایجاد کرده‌اید. با این کار می‌توان نام‌های متفاوتی را برای ستون‌های جداول در پایگاه داده و آنچه که در عمل با آن در حال کار هستید، ایجاد کرد. فیلد type هم بیانگر نوع فیلد شما در جدول پایگاه داده است.

<!–[if gte mso 9]> Normal 0 false false false EN-US X-NONE AR-SA <![endif]–><!–[if gte mso 9]> <![endif]–><!–[endif]–>

<property name=«Name« column=«DeptName« type=«String(50)«/>

مورد جالب در اینجا فیلد id از کلاس Department است. هر کلاس باید فیلدی داشته باشد که شامل داده‌ای باشد که یکتاست. در مثال ما هر کلاس یک شناسه id دارد که یکتاست. در اینجا شما باید یک مجموعهٔ استاندارد از صفات را فراهم کنید که مهم‌ترینشان Generator نام دارد و مشخص می‌کند که این داده چطور درست شده (توسط برنامه‌نویس یا بوسیله NHibernate یا توسط لایه‌های پایین‌تر).
Applicationهای مختلف قوانین مختلفی دربارهٔ شناسه‌ها دارند و پایگاه‌های‌داده مختلف سرویس‌های unique ای را برای مدیریت مقادیر پیشنهاد می‌کنند. در اینجا به چند مورد اشاره می‌کنیم.

مقادیر رایج برای generator ها:

1. Identity

2. Sequence

3. Hilo : استفاده از الگوریتم hilo برای generate کردن مقادیر شناسه‌ها.

4. Native : انتخاب خود DataBase

شناسهٔ unsaved_value یک مقدار default برای مشخصهٔ id است. یعنی وقتی که یک object ساخته شده ولی هنوز ذخیره نشده.

در اینجا ما native را انتخاب می‌کنیم. تا آنچه را که در پایگاه داده تعیین کرده‌ایم به عنوان id قرار بگیرد.

<id name=«Id« column=«DeptID« type=«Int32«>

<generator class=«assigned« />

</id>

حالا کد ما به این شکل درآمده:

<!–[if gte mso 9]> Normal 0 false false false EN-US X-NONE AR-SA <![endif]–><!–[if gte mso 9]> <![endif]–><!–[endif]–>

<?xml version=«1.0« encoding=«utf-8« ?>

<hibernate-mapping xmlns=«urn:nhibernate-mapping-2.0«>

<class name=«nhRegistration.Department, nhRegistration» table=«Department«>

<id name=«Id« column=«DeptID« type=«Int32«>

<generator class=«assigned« />

</id>

<property name=«Name« column=«DeptName« type=«String(50)«/>

</class>

</hibernate-mapping>

سپس به جمع‌آوری property ها می‌پردازیم (هر کدام که بخصوص باشند). بیایید به اولین کلاس‌مان نگاهی بیاندازیم که مجموعه‌ای از کلاس‌ها در دانشگاه است. نیازها و مدل‌ها را به خاطر داریم: یک دانشگاه می‌تواند چندین کلاس داشته باشد اما کلاس متعلق به یک دانشگاه است. این یک ارتباط یک به چند است. برای مدل کردن آن نیاز به element های <set> داریم که نشان دهیم که مجموعه‌ای را مپ می‌کنیم.

<set name=«Classes« cascade=«all«>

<key column=«DeptID«/>

<one-to-many class=«nhRegistration.UniversityClass,nhRegistration«/>

</set>

به عبارت ساده‌تر با کد بالا، مقادیر کلید DeptID که در جدول خودش PrimaryKey است، به ستون مشخص شده‌اش Map می‌شود. نشانهٔ name در <set> نام یک فیلد است که مجموعه را نگه می‌دارد. در اینجا column در <key>  نام یک ستون در مجموعه‌ای است که به مشخصهٔ id کلاس والد مپ می‌شود و <one_to_many> نوع کلاس گردآوری شده است. به این معنی که رابطه این ستون (فیلد) با ستون دیگر به چه صورتی است ( پایین‌تر به انواع دیگری هم اشاره می‌کنیم)
بنابراین جدولuniversity یک فیلد به نام deptid دارد که به id در کلاس university ی ما مپ می‌شود.
سرانجام ما باید فیلد professors را مپ کنیم. مدلمان را به خاطر بیاورید، دانشگاه می‌تواند چندین استاد داشته باشد و اساتید نیز می‌توانند در چندین دانشگاه مشغول به کار باشند. این یک ارتباط چند به چند است. که در زیر نمونه‌ای از آن را مشاهده می‌کنید، در پیاده سازی صرفا کلمه کلیدی one-to-many و many-to-many تفاوت می‌کند.

<!–[if gte mso 9]> Normal 0 false false false EN-US X-NONE AR-SA <![endif]–><!–[if gte mso 9]> <![endif]–><!–[endif]–>

<set name=«Professors« table=«departmentprofessor«>

<key column=«DeptID«/>

<many-to-many class=«nhRegistration.Person,nhRegistration» column=«Personid«/>

</set>

حال مپینگ کامل زیر را بخوانید

<!–[if gte mso 9]> Normal 0 false false false EN-US X-NONE AR-SA <![endif]–><!–[if gte mso 9]> <![endif]–><!–[endif]–>

<?xml version=«1.0« encoding=«utf-8« ?>

<hibernate-mapping xmlns=«urn:nhibernate-mapping-2.0«>

<class name=«nhRegistration.Department, nhRegistration«

table=«Department«>

<id name=«Id« column=«DeptID« type=«Int32«>

<generator class=«assigned« />

</id>

<property name=«Name« column=«DeptName« type=«String(50)«/>

<set name=«Classes« cascade=«all«>

<key column=«DeptID«/>

<one-to-many class=«nhRegistration.UniversityClass,nhRegistration«/>

</set>

<set name=«Professors« table=«departmentprofessor«>

<key column=«DeptID«/>

<many-to-many class=«nhRegistration.Person,nhRegistration« column=«Personid«/>

</set>

</class>

</hibernate-mapping>

اگر ما با استفاده از این مپینگ‌ها سعی کنیم که پروژه را load کنیم، موفق نمی‌شویم. NHibernate یک exception را گزارش می‌دهد زیرا ارتباطات یک به چند و چند به چند داریم. وقتی ارتباطاتی شبیه این داریم که NH هر دو طرف آن است باید نوع آنها را هم مپ کنیم.

<!–[if gte mso 9]> Normal 0 false false false EN-US X-NONE AR-SA <![endif]–><!–[if gte mso 9]> <![endif]–><!–[endif]–>

<?xml version=«1.0« encoding=«utf-8« ?>

<hibernate-mapping xmlns=«urn:nhibernate-mapping-2.0«>

<class name=«nhRegistration.UniversityClass, nhRegistration«

table=«UniversityClass«>

<id name=«Id« column=«DeptId« type=«Int32«>

<generator class=«assigned« />

</id>

<property name=«Name« column=«ClassName» type=«String(50)«/>

<many-to-one name=«Dept« class=«nhRegistration.Department,nhRegistration« column=«DeptID«/>

</class>

</hibernate-mapping>

تنها element جدید در این فایل <many_to_one> است که نمایندهٔ طرف دیگر <one_to_many>  در Department.hbm.xml است.

نوبت به professor می‌رسد که از همه جالب‌تر است، زیرا هم از interface ای بنام person به ارث رفته و هم یک جدول مشترک با دانشجو دارد. برای تشخیص professor و student باید به NH بگوییم که نوع موجودیت چیست و در  <discriminator> آن را مشخص می‌کنیم.

اگر نگاهی به مدل بیاندازید person ،3 فیلد را مشخص می‌کند: id ، person و lastname. student و professor هر دو این نمایندهٔ این فیلدها هستند اما آنه اتفاوت دارند. Student ، ssn دارد در حالی که professor ، identifier دارد. Professor مجموعه‌ای از دانشگاه‌ها و کلاسها را دارد در حالی که student فقط مجموعه‌ای از کلاس‌ها (ی درس) را دارد. شما می‌توانید فیلدها را در کلاس person مپ کنید اما فیلدهایی را که خاص هستند به عنوان subtype در <subclass> مپ کنید.

در حقیقت برای ثبت فضا‌، مجموعه مختلفی از فایل‌های مپ شده را برای پر‌رنگ کردن feature‌های polymorphism related ادغام می‌کنیم. این مجموعه به نظر می‌رسد شبیه مثال‌های بالا باشد.

<?xml version=«1.0« encoding=«utf-8« ?>

<hibernate-mapping xmlns=«urn:nhibernate-mapping-2.0«>

<class name=«nhRegistration.Person, nhRegistration« table=«People«>

<id name=«Id« column=«PersonID« type=«Int32«>

<generator class=«assigned« />

</id>

<discriminator column=«PersonType« type=«String«/>

<property name=«FirstName« column=«FirstName» type=«String(50)«/>

<property name=«LastName« column=«LastName» type=«String(50)«/>

<subclass name=«nhRegistration.Professor, nhRegistration» discriminator-value=«Professor«>

<property name=«Identifier« column=«Identifier» type=«String«/>

</subclass>

<subclass name=«nhRegistration.Student, nhRegistration» discriminator-value=«Student«>

<property name=«SSN« column=«Identifier» type=«String«/>

</subclass>

</class>

</hibernate-mapping>

با انجام کارهای بالا شما یک پروژه را با موفقیت به پایگاه داده مپ کرده‌اید. در مطالب بعدی نحوه استفاده از این کلاس‌ها را مرور خواهیم کرد.
منابعی که در نگارش این مطلب بکار رفته است.

  1. آوریل 26, 2009 در 7:14 ق.ظ. | #1

    جالب بود ، موفق باشيد

  2. بهار
    اوت 25, 2009 در 10:37 ق.ظ. | #2

    سلام دوست عزيز
    مطالبت فوق العاده بود و من خيلي كامل روند كار رو ياد گرفتم
    فقط يك مطلبي؟
    هيچ tools وجود ندارد كه بصورت اتوماتيك اين XMLMapp ها را بسازد؟؟!!!

  3. me
    سپتامبر 5, 2009 در 11:44 ب.ظ. | #3

    Microsoft visio برات حتی اسکریپت های SQL رو هم میسازه

  4. afshin.hajian
    اکتبر 24, 2009 در 11:31 ق.ظ. | #4

    سلام
    میگم شما قصد ازدواج ندارید؟

  1. هنوز دنبالکی دریافت نشده.

پاسخی بگذارید

در پایین مشخصات خود را پر کنید یا برای ورود روی شمایل‌ها کلیک نمایید:

نشان‌واره‌ی وردپرس.کام

شما در حال بیان دیدگاه با حساب کاربری WordPress.com خود هستید. بیرون رفتن / تغییر دادن )

تصویر توییتر

شما در حال بیان دیدگاه با حساب کاربری Twitter خود هستید. بیرون رفتن / تغییر دادن )

عکس فیسبوک

شما در حال بیان دیدگاه با حساب کاربری Facebook خود هستید. بیرون رفتن / تغییر دادن )

درحال اتصال به %s

دنبال‌کردن

هر نوشته‌ی تازه‌ای را در نامه‌دان خود دریافت نمایید.