‫NHibernate Caching و نوع Fetch در Entityها

موقع فعال‌سازی Cache در NHibernate متوجه شدم که فراخوانی بعضی Entityها و بعضی از Queryها از دیتابیس شامل چند join است و عملاً از آن چیزی که در Cache ممکن است موجود باشد استفاده‌ای نمی‌شود. به عنوان مثال فرض کنید کلاس Teacher و Student موجود باشد به نحوی که از کلاس Student یک Association به کلاس Teacher موجود باشد به اسم MyTeacher. حال اگر با متود Load یا Get یک رکورد از Student را از دیتابیس فراخوانی کنیم به طور معمول با چنین چیزی مواجه می‌شویم:

select col1, col2, … from student s left outer join teacher t on s.myteacher_id = t.id where …
همان طور که مشاهده می‌شود اگر تمام Teacherها هم در Cache موجود باشد باز هم به آنها مراجعه نشده و مورد استفاده قرار نخواهند گرفت چون query بالا خودش راساً اقدام به load رکورد teacher مربوطه می‌کند.

این موضوع جای نگرانی ندارد چون می‌توان NHibernate را مجبور کرد که از join استفاده نکرده و query بالا را به دو query زیر بشکند:

select col1, col2, … from student s where …

select col1, col2, … from teacher t where id = …

در این حالت اگر teacher مورد نظر ما در Cache موجود باشد، query دوم اطلاعاتش را به جای دیتابیس از Cache می‌خواند.

برای مجبور کردن NHibernate به عدم استفاده از join در سطح Load/Get مربوط به Entityها باید از property خاصی به اسم fetch در تعریف associationها در mapping کلاس مربوطه استفاده کرده و مقدار آن را برابر select قرار داد. مقدار پیش‌فرض این property برابر join است. برای انجام همین کار در Castle ActiveRecord باید از property خاصی به اسم Fetch استفاده کرد.

برای آن که در queryهای دیتابیسی مثل LINQ-to-NHibernate، HQL، ICriteria یا QueryOver هم همین کار را انجام داد باید از روش‌های متفاوت و جداگانه‌ای استفاده نمود.