‫داستان بی‌سوادی ما – ۶: Application Pool

یکی از مشکلات عجیب و غریب ما این بود که یکی از پروژه‌های ما مشکلات عجیبی با IIS داشت. این پروژه (الف) از پروژه‌ی دیگری (ب) مشتق شده بود. یعنی هر آن چه که در پروژه‌ی «ب» موجود بود در پروژه‌ی «الف» هم بود. پروژه‌ی «ب» هیچ مشکلی نه در ASP.NET Development Server و نه در IIS نداشت. اما پروژه‌ی «الف» در ASP.NET Development Server درست کار می‌کرد ولی در IIS نه.

این موضوع باعث اختلاف نظرهای زیادی شده بود. تا این که یک روز فهمیدم مشکل پروژه‌ی «الف» کجاست. علت، مقایسه‌ی آبجکت‌ها در حافظه بدون استفاده از ID آنها بود. این مقایسه در ASP.NET Development Server درست کار می‌کرد ولی در IIS درست کار نمی‌کرد. بعد از رفع مشکل هنوز این سوال برایم وجود داشت که چرا پروژه‌ی «ب» دچار چنین مشکلی نشده بود؟

یک روز که دنبال چیز دیگری در IIS بودم متوجه شدم که هر کدام از این پروژه‌ها از یک Application Pool مختلف برای کار خود استفاده می‌کنند. پروژه‌ی «ب» از Classic .NET AppPool استفاده می‌کرد ولی پروژه‌ی «الف» از DefaultAppPool. فرق این دو هم فقط در Pipline بود. اولی Classic بود و دومی Integrated. محض امتحان یک بار Application Pool پروژه‌ی «الف» را به Classic عوض کردم و آن مقایسه‌ای آبجکتی را دوباره به حالت بدون ID برگرداندم. در کمال ناباوری مشکل اولیه‌ی پروژه‌ی «الف» حل شد!

در واقع مشکل پروژه‌ی «الف» را می‌شد با درک بهتری از Pipeline زودتر کشف کرد که به علت بی‌سوادی و بی‌اطلاعی این موضوع اتفاق نیفتاده بود. البته الان می‌دانم علت خرابی کار Pipeline بوده ولی هنوز هم درک نمی‌کنم چرا.

‫داستان بی‌سوادی ما – ۵: SQL Server Profiler‫

یکی از ابزارهایی که هم برای خطایابی خیلی استفاده می‌شود و هم برای پیدا کردن مشکلات سرعت Queryهای دیتابیسی، ابزار SQL Server Profiler است. من هم از این ابزار خیلی استفاده کرده و می‌کنم. اما مشکل من با این ابزار حجم زیاد log تولیدی آن است. گاهی اوقات برای دیدن یک Query خاص باید چند صد رکورد را بالا و پایین کنم تا به رکورد مورد نظرم برسم. هر چند که این مشکل خیلی آزار دهنده بود ولی چون چاره‌ی دیگری نداشتم مجبور بودم همچنان از Profiler استفاده کنم.

اما همین چند وقت از طریق مطلبی در وبلاگ وحید و نیز توضیحات یکی از دوستان فهمیدم که می‌شد با یک تنظیم بسیار کوچک، حجم log مربوطه را به شدت کاهش داده و خیلی سریع‌تر به اطلاعات مورد نظرم دسترسی پیدا کنم.

نمی‌دانم این بی‌سوادی ناقابل تا حالا چند صد ساعت وقتم را تلف کرده است. اما به هر حال نحوه‌ی فیلتر کردن اطلاعات بسیار ساده بوده و کافی بود تا از طریق برگه‌ی Event Selection، اطلاعات را بر حسب «نام کاربری» و… فیلتر کنم. برای کسب اطلاعات بیشتر به اصل مطلب در وبلاگ وحید مراجعه کنید.

این مطلب جزیی از سری نوشته‌های «داستان بی‌سوادی ما» است.

‫‫‫‫داستان بی‌سوادی ما – ۴: Visual Studio Debugging

یکی از جاهایی که کار می‌کردم دو تا Solution خیلی بزرگ داشتیم. اولی که ۶۴ تا پروژه‌ی ویژوال استودیو بود که همگی تبدیل به dll می‌شدند و دومی که یک پروژه‌ی وب حجیم بود با چیزی بالای ۶۰۰ صفحه aspx. بعضی وقت‌ها که ایرادی پیش می‌آمد مجبور می‌شدم Solution اول را روی کامپیوتر خودم Build کنم، dllهایش را به Solution دوم اضافه کنم، Solution دوم را در حالت Debug بالا بیاورم، آن صفحه‌ای را که مشکل را داشت را باز کنم، روی آن خطی که dllهای Solution اول را صدا می‌زد Break Point بگذارم و هر وقت که اجرای برنامه به آن خط می‌رسید آنقدر F11 می‌زدم و از کلاس‌ها و متودهای مختلف رد می‌شدم تا به آنجایی که تازه می‌خواستم وجود یا عدم وجود ایراد را بررسی کنم برسم. این پروسه خودش در بهترین حالت ۲۰ دقیقه طول می‌کشید تازه بعضی وقت‌ها علت خطا را پیدا کرده و درست می‌کردم و می‌خواستم دوباره آن را امتحان کنم، این خودش یعنی ۲۰ دقیقه‌ی دیگر. حالا خودتان حساب کنید بعضی روزها که می‌افتادیم روی دنده‌ی Debug، چقدر باید وقتمان تلف می‌شد.

چند بار سعی کرده بودم این پروسه را با فراخوانی dllها در یک برنامه‌ی ویندوزی آزمایشی، حذف موقتی بعضی صفحات کم استفاده‌ی Solution دوم، استفاده از Unit Test، استفاده از logging و… کوتاه‌تر و بهینه‌تر کنم اما چندان موفق نبودم. چون به هر صورت بعضی چیزها را فقط در خود پروژه‌ی وب می‌توانستم Debug کنم. متاسفانه این بعضی چیزها خیلی کم تعداد نبودند و همیشه روی اعصاب من و بقیه راه می‌رفتند تا آنجا که بعضی وقت‌ها درخواست‌های Debug یک بخش را کلاً بی‌خیال شده و آن بخش را مجدداً بازنویسی می‌کردم یا این که ایرادهایی را که می‌دانستم قطعاً وجود دارند را مدام پشت گوش می‌انداختم چون واقعاً اعصاب و وقت دیباگ همچون پروژه‌ی حجیمی را نداشتم.

البته تا اینجای کار فقط یک حالت مشکل را شنیدید. حالت دیگر آن وقتی است که امکان استفاده از Break Point را ندارید و اصلاً نمی‌توانید Debug کنید. مثل وقتی که یک عملیاتی از قبیل Data Binding یا به روز رسانی اطلاعات از طریق کدهای Markup یا Declarative صفحات aspx انجام می‌شود.

این مشکلات چند سال است که گریبان‌گیر من است و من دیگر وجود آن را قبول کرده بودم تا این چند وقت پیش با یک ور رفتن کوچولو با StackOverflow فهمیدم که چقدر تا حالا وقتم بیهوده تلف می‌شده است. چون می‌توانستم به راحتی آب خوردن از گزینه Attach to Process ویژوال استودیو برای این کار استفاده کنم بدون آن که این همه وقتم تلف شود.

روش کار بدین صورت است که اول آن Solution وبی را باز می‌کنید و بدون حالت Debug به اجرا در می‌آورید. بعد Solution حاوی dllها را باز کرده و مطمئن شوید که به غیر از فایل‌های dll، فایل‌های pdb را هم دارید. البته اگر ندارید نگران نباشید. این فایل‌ها با یک بار Build به طور خودکار ساخته می‌شوند. قدم بعدی انتخاب گزینه‌ی Attach to Process از منوی Debug ویژوال استودیویی است که Solution حاوی dllها در آن باز است. حالا از فهرست پیش رو، process مربوط به ASP.NET Web Development Server را که معمولاً اسمش با WebDev شروع می‌شود را انتخاب نمایید. در این لحظه ویژوال استودیو خود به خود به حالت Debug می‌رود. شما می‌توانید هر جا که خواستید Break Point بگذارید. اگر به آن صفحه‌ای که نهایتاً آن کد را اجرا می‌کند بروید، می‌بینید که ویژوال استودیوی حاوی dll در محل Break Point انتخابی شما آماده دریافت F10 و F11 است. به همین سادگی! این کار حتی در مورد کدهایی هم که به طور مستقیم از markup صدا زده می‌شوند نیز قابل انجام است.

به عنوان سورپریز این قضیه را داشته باشید که می‌توانید عین همین کار را بدون اجرا کردن پروژه‌ی وبی از طریق ویژوال استودیوی اول هم انجام دهید البته به شرطی که همان پروژه را در IIS کامپیوترتان داشته باشید. روش کار به این صورت است که در بخش Attach to Process به جای Web Development Server از process مربوط به IIS که اسمش در ویندوز دو هزار و هشت w3wp است استفاده کنید.

سورپریز دومی هم وجود دارد. می‌توانید به جای استفاده از IIS کامپیوتر خودتان از IIS دیگر کامپیوترها هم استفاده کنید. یعنی می‌توانید از طریق ویژوال استودیوی کامپیوتر خودتان Web Applicationهایی که در IIS یک کامپیوتر دیگر نصب هستند را Debug کنید. اسم این کار Remote Debugging است.

‫داستان بی‌سوادی ما – ۳: ASP.NET Membership

یکی از امکانات ASP.NET مجموعه Membership و امکانات جانبی آن است. این مجموعه به برنامه‌های ASP.NET امکان تعریف کاربر، نقش و کنترل دسترسی بر اساس آنها را می‌دهد. برای این که بتوان از این امکانات استفاده کرد بایستی موارد مورد نیاز ASP.NET applications services در بانک اطلاعاتی مورد استفاده برنامه نصب گردد. این کار به طور معمول با کمک ابزار aspnet_regsql.exe انجام می‌شود.

بنده هم هر وقت که می‌خواستم یک بانک اطلاعاتی را برای یک برنامه ASP.NET آماده کنم از همین ابزار aspnet_regsql.exe استفاده می‌کردم. البته بعدها در این کار پیشرفت کرده و جای این اسکریپت‌ها را در ویندوز پیدا کرده بودم:

 C:WindowsMicrosoft.NETFrameworkv4.0.30319
من می‌خواستم انجام کار را خودکار کنم به همین دلیل آن اسکریپت‌ها را از طریق کد باز کرده، اسم بانک اطلاعاتی خودم را به جای اسم پیش‌فرض آن می‌گذاشتم و دست آخر با هزار زحمت آن از طریق کدهای C#‎ در داخل دیتابیس اجرا می‌کردم. این کارها واقعاً وقت‌گیر و پردردسر بودند. چون انجام کامل آن و دیباگ آن حدود ۳ روز طول می‌کشید. علاوه بر آن وقتی از شرکتی به شرکتی دیگر نقل مکان می‌کردم دیگر نمی‌توانستم از آن کدهای قبلی استفاده کنم و باید آنها را دوباره از اول می‌نوشتم.

حال نکته بی‌سوادی من اینجاست که به تازگی متوجه شدم که کل این کارها با فراخوانی یک متود ساده هم قابل انجام بود! به کد زیر توجه کنید:

SqlServices.Install("databaseName", SqlFeatures.All, "connectionString");
این کلاس با ارزش در فضای نام System.Web.Management قرار دارد. جهت کسب اطلاع بیشتر به این لینک مراجعه کنید.

توجه: این نوشته در قالب سری نوشته‌های «بی‌سوادی ما» می‌باشد.

‫داستان بی‌سوادی ما – ۲

چند ماه پیش بعد از این که متوجه شده بودم ما در بحث Error Handling برنامه‌هایمان حسابی وقت تلف کرده‌ایم و می‌توانستیم آن کار را خیلی راحت‌تر، سریع‌تر و موثرتر انجام دهیم، حسابی از دست خودم و بقیه کسانی که می‌توانستند متوجه این امکانات بهتر شوند ولی نشده بودند شاکی شده بودم.

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

یکی از راه‌های جلوگیری از این احساس حماقت‌ها این است که در حوزه‌ی فناوری‌های مورد استفاده خود حسابی خبره شده و هیچ کتاب، خبر یا وبلاگی را از دست ندهیم. اما متاسفانه این راه اقلاً برای من امکان‌پذیر نیست. چون من مثل یک برنامه‌نویس آمریکایی نیستم که فقط در یک محدوده‌ی خاص فعالیت کنم. من به طور هم‌زمان باید با مجموعه‌ای قابل توجهی از فناوری‌های هر چند به طور سطحی کار کنم. از جمله: C#‎، ASP.NET، XML، XSLT، JavaScript، MS SQL Server، NHibernate، Castle ActiveRecord، Network Programming، WPF، TFS، SVN، ‌Build Automation، Agile، Scrum، Ajax، UML، Visual Studio، Unit Test، LINQ، Windows و…

مع‌الوصف به خاطر این که کاری کرده باشم و همینجوری دست روی دست نگذاشته باشم، تصمیم گرفته‌ام که بی‌سوادی‌های جدیدم را مکتوب کنم. شاید اقلاً درد بقیه را قبل از آن که به آن دچار شوند مداوا کند.