۱۳۸۹/۰۹/۲۸

يكسان سازي ي و ك دريافتي حين استفاده از NHibernate



تصوير فوق، يكي از تصويرهايي است كه شايد از طريق ايميل‌هايي تحت عنوان "فقط در ايران!" به دست شما هم رسيده باشد. تصور كاربر نهايي (كه اين ايميل را با تعجب ارسال كرده) اين است كه در اينجا به او گفته شده مثلا "مرتضي" را جستجو نكنيد و امثال آن. چون براي او تفاوتي بين ي و ى وجود ندارد. همچنين بكار بردن "اقلامي" هم كمي غلط انداز است و بيشتر ذهن را به سمت كلمه سوق مي‌دهد تا حرف.

در ادامه‌ي بحث آلرژي مزمن به وجود انواع "ي" و "ك" در بانك اطلاعاتي (+ و + و +)، اينبار قصد داريم اين اطلاعات را به NHibernate بسط دهيم. شايد يك روش اعمال يك دست سازي "ي" و "ك" اين باشد كه در كل برنامه هر جايي كه قرار است update يا insert ايي صورت گيرد، خواص رشته‌اي را يافته و تغيير دهيم. اين روش "كار مي‌كنه" ولي ايده آل نيست؛ چون حجم كار تكراري در برنامه زياد خواهد شد و نگهداري آن هم مشكل مي‌شود. همچنين امكان فراموش كردن اعمال آن هم وجود دارد.
در NHibernate يك سري EventListener وجود دارند كه كارشان گوش فرا دادن به يك سري رخدادها مانند مثلا update يا insert است. اين رخدادها مي‌توانند پيش يا پس از هرگونه ثبت يا ويرايشي در برنامه صادر شوند. بنابراين بهترين جايي كه جهت اعمال اين نوع مميزي (Auditing) بدون بالا بردن حجم برنامه يا اضافه كردن بيش از حد يك سري كد تكراري در حين كار با NHibernate مي‌توان يافت، روال‌هاي مديريت كننده‌ي همين EventListener ها هستند.

كلاس YeKeAuditorEventListener نهايي با پياده سازي IPreInsertEventListener و IPreUpdateEventListenerبه شكل زير خواهد بود:
using NHibernate.Event;

namespace NHYeKeAuditor
{
public class YeKeAuditorEventListener : IPreInsertEventListener, IPreUpdateEventListener
{
// Represents a pre-insert event, which occurs just prior to performing the
// insert of an entity into the database.
public bool OnPreInsert(PreInsertEvent preInsertEvent)
{
var entity = preInsertEvent.Entity;
CorrectYeKe.ApplyCorrectYeKe(entity);
return false;
}

// Represents a pre-update event, which occurs just prior to performing the
// update of an entity in the database.
public bool OnPreUpdate(PreUpdateEvent preUpdateEvent)
{
var entity = preUpdateEvent.Entity;
CorrectYeKe.ApplyCorrectYeKe(entity);
return false;
}
}
}
در كدهاي فوق روال‌هاي OnPreInsert و OnPreUpdate پيش از ثبت و ويرايش اطلاعات فراخواني مي‌شوند (همواره و بدون نياز به نگراني از فراموش شدن فراخواني كدهاي مربوطه). اينجا است كه فرصت داريم تا تغييرات مورد نظر خود را جهت يكسان سازي "ي" و "ك" دريافتي اعمال كنيم (كد كلاس CorrectYeKe را در پيوست خواهيد يافت).

تا اينجا فقط تعريف YeKeAuditorEventListener انجام شده است. اما NHibernate چگونه از وجود آن مطلع خواهد شد؟
براي تزريق كلاس YeKeAuditorEventListener به تنظيمات برنامه بايد به شكل زير عمل كرد:
using System;
using System.Linq;
using FluentNHibernate.Cfg;
using NHibernate.Cfg;

namespace NHYeKeAuditor
{
public static class MappingsConfiguration
{
public static FluentConfiguration InjectYeKeAuditorEventListener(this FluentConfiguration fc)
{
return fc.ExposeConfiguration(configListeners());
}

private static Action<Configuration> configListeners()
{
return
c =>
{
var listener = new YeKeAuditorEventListener();
c.EventListeners.PreInsertEventListeners =
c.EventListeners.PreInsertEventListeners
.Concat(new[] { listener })
.ToArray();
c.EventListeners.PreUpdateEventListeners =
c.EventListeners.PreUpdateEventListeners
.Concat(new[] { listener })
.ToArray();
};
}
}
}
به اين معنا كه FluentConfiguration خود را همانند قبل ايجاد كنيد. درست در زمان پايان كار تنها كافي است متد InjectYeKeAuditorEventListener فوق بر روي آن اعمال گردد و بس (يعني پيش از فراخواني BuildSessionFactory).

كدهاي NHYeKeAuditor را از اينجا مي‌توانيد دريافت كنيد.