بایگانی

نوشته‌هایی که ‘Transaction’ برچسب زده شده‌اند

ساخت، load و ذخیره کردن آبجکت‌ها در NHibernate

ژوئیه 7, 2009 بیان دیدگاه
از آنجایی که هدف از session فراهم کردن مکانیزمی برای مدیریت کارایی برنامۀ شماست و در حقیقت این مدیریت برای پیشگیری از round trip ها در DataBase است، منطقی است که عملیات روی session همیشه نتیجۀ عملیات زیرساختی DataBase نیست (نباشد). در حقیقت آن یک اشاره‌گر به session برای cache کردن عملیات است تا اینکه آنها بتوانند در دیتابیس ذخیره شوند، بدینگونه round trip ها ذخیره می شوند. همۀ اینها بدین معنی است که وقتی که شما یک متد پایدار را در session صدا می کنید، با تغییرات آنی در database ممکن است که جواب بدهد یا ندهد.
معمولا تغییرات فقط هنگامی در دیتابیس ذخیره می شوند که متد session’s flush() صدا زده شوند.شما می توانید مستقیما این را انجام دهید.اما بیشتر رایج است که flush() را در پایان عملیات صدا کنیم.
اگر شما یک برنامۀ دیتابیسی ساخته باشید اما به این تراکنش‌ها علاقمند نباشید، باید زمانی را به بهبود طرحتان اختصاص دهید. لازم است که وقتی که حتی Query‌ها را دستی می‌نویسید مطمئن باشید که واحد اتمیک تغییرات را به دیتابیس اعمال می کند. این قضیه اهمیت بیشتری پیدا می کند وقتی که از لایۀ ORM ی مانند NHibernate استفاده می شود. زیرا یک دستورالعمل ساده مانند save(dept) می‌تواند تغییر حاصله را در چندین بخش از دیتابیس مانند professor ،classes و یا روی join table ها اعمال کند. اگر هر کدام از این تغییرات fail شود و شما هیچ مدیریتی بر آنچه که می‌نویسید نداشته باشید، دیتابیس شما بلااستفاده رها خواهد شد. بنابراین زمانی که از NHibernate استفاده می کنید از session ها بدون تراکنش استفاده نکنید. الگوی استفاده رایج به این صورت می‌باشد:

ISession session;
ITransaction tx;
try
}
session = factory.OpenSession();
tx = session.BeginTransaction();
// do database work
tx.Commit();
session.Close();
{
catch (Exception ex(
}
tx.Rollback();
session.Close();
// further exception handling
{

نویسندگان مستندات Hibernate مصرانه پیشنهاد می‌کنند که هرگز یک exception را بازیابی نکنید زیرا بازیابی تراکنش به عنوان اولین قدم در handle کردن Exception ها در ابتدای برنامه قرار دارند. این خیلی مهم است زیرا NHibernate به صورت آبشاری مدیریت می کند.
جایی که به مشکل بخورند خودشان را نشان می‌دهند. بهترین نظر این است که همه چیز را به حالت اول برگردانید، در دامنه مدلتان مشکل را حل کنید و دوباره سعی کنید.
بگذارید راجع به انواع رایج فعالیت‌ها برای object های ماندگارمان صحبت کنیم. خب، دیدید که پیاده‌سازی سه متد اول interface DBMgr در بالا نمایش داده شد.متد getDepartments() لیستی از بخش های ِDepartment را برمی گرداند.

public IList getDepartments()
{
IList depts = null;
try
{
ISession session = factory.OpenSession();
ITransaction tx = session.BeginTransaction();
depts = session.CreateCriteria(typeof(Department)).List();
session.Close();
}
catch (Exception ex)
{
tx.Rollback();
session.Close();
// handle exception.
}
return depts;
}

آبجکت session نشان می‌دهد متد createcriteria() که به عنوان آرگومان، یک نوع کلاس پایدار را می‌گیرد. این نشان می‌دهد که NHibernate با تبدیل های مپ شده به آبجکت ها فعل و انفعال‌ها را تندتر می‌کند. در نتیجه list() نتایج برگشتی از تمامی interface های موجود را برمی‌گرداند. در این مورد بهتر است یک لیست شامل خواصی از Department را برگردانیم.که با دیتابیس کاملا یکی است (شامل تمام دیگر آبجکت های مرتبط با department). این متد صریحی است که استفاده می‌شود که در دیتابیس شما در میان تمام interface های کلاس تکرار می‌شود.
اگر شما می خواهید interface مشخصی از database را تکرار کنید شما باید مقادیر مشخص از شناسه فیلدها را برای کلاس هدف بدانید که شما دنبال آن هستید.

public Department getDepartment(int i)
{
Department d = null;
try
{
ISession session = factory.OpenSession();
ITransaction tx = session.BeginTransaction();
d = (Department)session.Load(typeof(nhRegistration.Department), i);
session.Close();
}
catch (Exception ex)
{
tx.Rollback();
session.Close();
// handle exception. }
return d;
}

فقط به خاطر داشته باشید که نتایج session.load() را به یک نوع مناسب object ای که برمی‌گرداند cast کنید.
در پایان آیا می‌خواهید تغییرات را در یک interface ذخیره کنید (یا یک interface جدید ایجاد کنید)؟ آیا session در متد برای شما session.save() را که برای ایجاد یک interface جدید به کار می‌رود در نظر گرفته است یا session update() که برای تغییر یک interface از session موجود به کار می رود؟ شما مجبورید که این دو را جدا در نظر بگیرید. اگر شما یک متد اشتباه را اجراکنید. تداخل session و خطاهای پایگاه داده رخ می‌دهد ، در interface ما با وجود اینکه پیاده‌سازی DBmgr فقط یک متد saveDepartment(Department dept) را دارد. این برای یک برنامۀ ساده عقلانی نیست که برنامه نویسان مجبور شوند بین ماندگار کردن یک object جدید و یک object از پیش موجود تفاوت قایل شوند به همین دلیل interface ما فقط یک متد دارد. در پیاده‌سازی ما هنوز نیازمند این تفلوت قایل شدن هستیم.

public void saveDepartment(Department dept)
{
try
{
ISession session = factory.OpenSession();
ITransaction tx = session.BeginTransaction();if(dept.Id == 0)
{
session.Save(dept);
}
else
{
session.Update(dept);
}
tx.Commit();
session.Close();
}
catch (Exception ex)
{
tx.Rollback();
session.Close();
// handle exception
}
}

ابتدا پیش از آنکه interface را ماندگار کنیم باید این را تشخیص دهیم که آیا از پیش وجود دارد یا اینکه جدید است. بوسیلۀ یک فیلد ساده تشخیص هویت integer ی، ما فقط ارزیابی می‌کنیم که مقدار آن صفر است یا نه. که این معنی را می‌دهد که هیچ ردیفی از قبل در پایگاه داده وجود ندارد. (صفت ثبت نشده را در بالا به یاد بیاورید). شما می‌توانید تصور کنید که این منطق، کاربردی در تشخیص هویت‌های پیچیده ندارد، هنگامی‌که ما در مورد از پیش وجود داشتن interface تصمیم‌گیری می‌کنیم، متد جدیدی را در session برای این کار در نظر می‌گیریم.

دسته‌ها:Programming برچسب‌ها: , , , , , , , , ,