‫پیغام خطاهای معروف NHibernate – قسمت اول

یکی از معروف‌ترین خطاهای NHibernate خطای زیر است:

No row with the given identifier exists[EntityName#rec_id]
به جای EntityName نام کامل entity و به جای ‎#rec_id شماره رکورد قرار می‌گیرد. این خطا همان طور که پیغامش اشاره می‌کند وقتی به وقوع می‌پیوندد که NH در دیتابیس به دنبال رکورد خاصی می‌گشته ولی آن رکورد در دیتابیس وجود نداشته است. معمولاً می‌توان ردی از Load یا Get را هم در StackTrace پیدا کرد. گاهی اوقات که rec_id چیز عجیب و غریبی باشد، این پیغام خطا گمراه کننده‌تر هم می‌شود. خصوصاً وقتی که از idهای نوع Guid استفاده شده باشد.

این پیغام خطا معمولاً خیلی زیاد به وجود می‌آید. بسیاری از کاربران، خصوصاً آنها که آشنایی کمتری با NH یا ORMها به طور کلی دارند، با دیدن این پیغام خطا دچار اشتباه شده و فکر می‌کنند NH دچار مشکل خاصی شده که باید با تلاش فراوان آن را حل کرد. این خطا در Data Binding صفحات ASP.NET هم خیلی زیاد دیده می‌شود. خصوصاً وقتی که ترتیب Bind کنترل‌ها به هم خورده و کنترلی زودتر از موقع DataBind شده. است. چیزی که خیلی مهم است این است که این پیغام خطا فقط نشانه است که کسی از NH خواسته که رکوردی را از دیتابیس فراخوانی کند. این مشکل NH نیست که آن رکورد وجود ندارد، بلکه خود برنامه باید بررسی گردد تا علت فراخوانی از دیتابیس مشخص گردد.

پیغام خطای کشنده

بعضی پیغام خطاها آنقدر سمج هستند و آن قدر منبع نامعلومی دارند که می‌توان به آنها لقب لعنتی، کشنده یا حتی دهن صاف کن داد.

به تازگی یکی از این پیغام خطاهای کشنده برای من اتفاق افتاد. زمانی که در حال فعال‌سازی Caching سطح دوم برای یک برنامه‌ی مبتنی بر Castle ActiveRecord بودم دچار خطای زیر شدم:

Unable to cast object of type ‘NHibernate.Caches.SysCache.SysCacheProvider’ to type ‘NHibernate.Cache.ICacheProvider’.

NHibernate.Caches.SysCache نام اسمبلی است که قابلیت Second Level Cache را به NHibernate و Castle Active Record اضافه می‌کند. ظاهر امر نشان می‌داد که بین اسمبلی‌ها مورد استفاده ناهمخوانی نسخه‌ای وجود دارد. مثلا NHibernate من نسخه 2.1 است ولی SysCache مورد استفاده نسخه 3.0 است. به همین دلیل بارها و بارها نسخه‌های متفاوت NHibernate و Castle و SysCache را از SourceForge دریافت کردم ولی مشکل حل نشد. سعی کردم به جای SysCache از دیگر Cache Providerها استفاده کنم ولی آن هم نشد. در ادامه این سعی و تلاش‌ها چندین بار تنظیمات Caching مورد استفاده را در web.config و mappingها چک کردم، سورس‌های Castle و SysCache را خودم کامپایل کردم و حتی به فکر افتادم خودم یک Cache Provider ساده بنویسم اما مشکل حل نشد که نشد.

خلاصه این که در اوج ناامیدی بودم که در یکی از آن «لحظات طلایی» متوجه علت خطا شدم. چون تعداد Assemblyهای مورد استفاده در ارتباط با NHibernate و Castle زیاد بود، یکی از دوستان آنها را با هم merge کرده بود تا یک اسمبلی واحد تشکیل گردد. من هم اسمبلی NHibernate.Caches.SysCache را در کنار اسمبلی فوق‌الذکر گذاشته بودم و در تنظیم cache.provider_class نام اسمبلی NHibernate.Caches.SysCache را ذکر کرده بودم، در حالی که باید اسمبلی NHibernate.Caches.SysCache را با مجموعه قبلی merge (با استفاده از ilmerge.exe) کرده و در cache.provider_class نام اسمبلی حاصل از merge را ذکر می‌کردم!