۱۳۸۹/۱۰/۰۲

NHibernate 3.0 و خواص تنبل (lazy properties)!


احتمالا مطلب "دات نت 4 و كلاس Lazy" را پيشتر مطالعه كرده‌ايد. هر چند NHibernate 3.0 بر اساس دات نت فريم ورك 3 و نيم تهيه شده، اما شبيه به اين مفهوم را در مورد بارگذاري به تاخير افتاده‌ي مقادير خواص يك كلاس كه به ندرت مورد استفاده قرار مي‌گيرند، پياده سازي كرده است. Lazy را در اينجا تنبل، به تعويق افتاده، با تاخير و شبيه به آن مي‌توان ترجمه كرد؛ خواص معوقه!
براي مثال فرض كنيد يكي از خواص كلاس مورد استفاده، متن، تصوير يا فايلي حجيم است. در مكاني هم كه قرار است وهله‌اي از اين كلاس مورد استفاده قرار گيرد نيازي به اين اطلاعات حجيم نيست؛ با ساير خواص آن سر و كار داريم و نيازي به اشغال حافظه و منابع سيستم در اين مورد خاص نيست.

سؤال: چگونه آن‌را تعريف كنيم؟
اگر از NHibernate سنتي استفاده مي‌كنيد (يا به عبارتي فايل‌هاي hbm.xml را دستي تهيه مي‌كنيد)، ويژگي Lazy را به صورت زير مي‌توان مشخص كرد:
<property name="Text" lazy="true"/>
اگر از Fluent NHibernate استفاده مي‌كنيد (و فايل‌هاي hbm.xml به صورت خودكار از كلاس‌هاي شما تهيه خواهند شد)، روش كار به صورت زير است (فراخواني متد LazyLoad روي خاصيت مورد نظر):
public class Post
{
public virtual int Id { set; get; }
public virtual string PostText { set; get; }
}

public class PostMappings : ClassMap<Post>
{
public PostMappings()
{
Id(p => p.Id, "PostId").GeneratedBy.Identity();
Map(p => p.PostText).LazyLoad();
//…
Table("Posts");
}
}
در اين حالت در پشت صحنه در مورد خاصيت PostText چنين نگاشتي تعريف خواهد شد:
<property name="PostText" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" lazy="true" />

سؤال: چه زماني نبايد از اين روش استفاده كرد؟
فرض كنيد در شرايطي ديگر نياز است تا اطلاعات تمام ركوردهاي جدول مذكور به همراه مقدار PostText نمايش داده شود. در اين حالت بسته به تعداد ركوردها، ممكن است هزاران هزار كوئري به ديتابيس ايجاد شود كه مطلوب نيست (به ازاي هربار دسترسي به خاصيت PostText يك كوئري توليد مي‌شود).

البته امكان لغو موقت اين روش تنها در حين استفاده از HQL (يكي ديگر از روش‌هاي دسترسي به داده‌ها در NHibernate) ميسر است. اطلاعات بيشتر: (+)