نظرات مطالب
فقط به خاطر یک نیم فاصله!
از اصلاح استاندارد ۲۹۰۱ سپاسگذارم و در ارتباط با
«اصولا استاندارد باید برگرفته از صنعت کشور باشد نه تحمیل بی منطق به آن.»

باید عرض کنم که با این مطلب موافقم اما دقت کنید که در استاندارد ۹۱۴۷ مزایای بسیاری هست که از آن جمله می توان به داشتن کاراکترهای RLE- lRE - RLO - LRO - و چند کاراکتر بدربخور دیگر و همچنین سایر کاراکترهای مورد نیاز در فارسی برای مثال حروف «» که باید در فارسی بجای () استفاده شوند نیز هست
گرچه خودمن در ۹۵ درصدر موارداز همین () استفاده می کنم و حتی اینکه سایر کیبورد ها هم در بعضی موارد این کلیدهای «» را در بردارند اما در نظر داشته باشید که گرداوری این کلیدها و چینش آن در کنار هم امر بسیار مهمی است.
من هم امیدوارم که در آینده صنعت کشور از تولید کیبوردهای غیراستاندارد دست برداشته و با فشار موسسه استاندارد از صفحه کلید جدید استفاده کند
خود من خیلی به تعویض این رویه با تعویض قالب استاندارد در خود ویندوز امیدوار هستم و سعی می کنم برای استفاده از این قالب کیبورد به همه گوشزدهای کافی را بکنم و شاید با این کار استفاده از فونت های غیراستاندارد و غیر یونیکد بخصوص فونتهای سری‫ B منسوخ شود
نظرات مطالب
فقط به خاطر یک نیم فاصله!
با اینکه معمولا از نوشته های شما استفاده می کنم اما عموما با نظر شما در استفاده از استانداردها مخالفم.
اینکه ما استاندارد منقرض شده ۲۹۰۱ و از آن بدتر ترکیب ی و ک عربی را استفاده کنیم نه بجاست و نه ارزشی دارد.
اصولا همین محتوایی هم که وجود دارد اشتباه است و این همه اشتباه را نباید ادامه داد. اینکه هیچ کیبورد فارسی کلمه پ و ژ را مطاق استاندارد ندارد دلیلی بر عدم استفاده نیست. خود من روی لپ تاپم هیچ حرف فارسی نوشته نشده و براحتی ا آن کار می کنم و به هیچ کسی هم جواب نمیدهم که چرا جای حروف به فلان شکل است.
در ضمن جهت اطلاع عرض کنم که جای پ و ژ در استاندارد ۲۹۰۱ هم دقیقا همین جایی بود که در ۹۱۴۷ هست و این دو کلید که شما ذکر کردید جای دیگری ندارد.
تا آنجا هم که من اطلاع دارم در اولین سرویس پک ویندوز ۷ قالب استاندارد ۹۱۴۷ جانشین قالب کیبورد فارسی غیر استاندارد ویندوز می شود و خود بخود یک بخش عظیمی از مشکلات حل می شود.
از شما هم خواهش می کنم که کلمه ۲۰۹۱ را با ۲۹۰۱ عوض کنید که خوانندگانی که اطلاع کافی راندارند و به خودشان هم برای مطالعه زحمت نمی دهند در آینده دچار مشکل نشوند.
در ضمن امیدوارم بزودی شاهد ستفاده شما از استاندارد ۹۱۴۷ باشیم و کیبوردی هم برایآن تولید شود
مطالب
استفاده از کتابخانه DotNetZip و CPUهای چند هسته‌ای
هرچند از دات نت 4 و نیم به بعد، الگوریتم Zip به صورت توکار پشتیبانی می‌شود، اما برای نگارش‌های پایین‌تر، کتابخانه DotNetZip جزو پرکاربردترین‌‌ها در این زمینه است.
از همین کتابخانه مدتی در یک سرور معمولی بدون مشکل استفاده کرده بودم تا اینکه پس از ارتقاء به سرور جدید با خراب بودن فایل‌های Zip حاصل مواجه شدم. پس از بررسی مشخص شد که این کتابخانه با CPUهای چند هسته‌ای مشکل دارد و باید این نوع پردازش موازی را در آن خاموش کرد:
using (var zf = new ZipFile())
{
   zf.UseUnicodeAsNecessary = true;
   zf.ParallelDeflateThreshold = -1;
   zf.Comment = "….";
   zf.AddFile(path, "programName");
   zf.Save(whereToSave);
}
همانطور که مشاهده می‌کنید، برای غیرفعال سازی پردازش موازی، فقط کافی است پارامتر ParallelDeflateThreshold با منهای یک مقدار دهی شود.
همچنین اگر نام فایل‌های شما فارسی است نیاز است UseUnicodeAsNecessary نیز به true تنظیم گردد.

در کل گاهی از اوقات همین نکات کوتاه می‌توانند از صدمات جدی در آینده جلوگیری کنند. خصوصا اگر از این محصول جهت تهیه پشتیبان استفاده شده باشد.
نظرات نظرسنجی‌ها
با توجه به امکانات جدید Razor Components، آیا در آینده از SPA frameworks استفاده میکنید؟
این فناوری مانند این هست که عنوان کنید از جاوا اسکریپت خسته شدم و الان می‌خوام با سیلورلایت کار کنم. نه پختگی فریم ورک‌های تک صفحه‌ای رو داره، نه معلوم هست که در آینده پشتیبانی میشه. دست آخر باز هم برای یکسری از کارهای پیشرفته مجبور میشید به ترکیبی از جی‌کوئری و کدهای فعلی برسید. دقیقا همون مشکلی که با ام وی سی وجود داره. برای ساخت یک فرم ساده فراتر از عالی هست. اما زمانیکه مجبور شدی کمی رابط کاربری پیچیده‌تری رو طراحی کنی، می‌رسی به یک ترکیب نافرم جاوا اسکریپت و کدهای Razor در یک صفحه که تمام شعار آزمون پذیری سیستم رو زیر سؤال می‌بره. فریم ورک‌های تک صفحه‌ای به لطف تایپ‌اسکریپت این مشکل رو حل کردن و می‌تونی یک لایه رابط کاربری بسیار پیچیده و همچنین قابل نگهداری و آزمایش رو توسعه بدی. 
مطالب
دسته بندی چابکانه

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

در این روش چهار دسته وجود دارد که هر فعالیت می‌تواند در آن دسته قرار بگیرد: (1) انجام شود، (2) موکول شود، (3) زمانبندی شود، (4) واگذار شود.

1) دسته اول کارهایی هستند که هم اکنون زمان انجام آنها فرا رسیده است. به این معنی که یا اکنون بهترین زمان انجام آنهاست، یا اگر آنها را به آینده موکول کنید مجبور خواهید بود انرژی و وقت بیشتری را صرف انجام آنها کنید.

2) دسته دوم کارهایی هستند که می‌بایستی انجام شوند اما اکنون زمان مناسبی برای انجام آنها نیست. بنابراین شما می‌توانید آنها را در صف انتظار قرار دهید و در آینده تصمیم بگیرید که با آنها چه کنید.

3) دسته سوم کارهایی هستند که برای شما اهمیت بالایی دارند، اما اکنون زمان مناسبی برای انجام آنها نیست. آنها را زمانبندی کنید. به این معنی که در تقویم خود برای انجام آنها یک زمان مشخص درنظر بگیرید تا در آن زمان انجام شوند.

با تخصیص دادن زمان به انجام یک کار در آینده فکر خود را از مشغولیت درباره آن آزاد می‌کنید. به طور مثال، شما می‌دانید که باید گزارش ماهیانه خود را در پایان ماه برای رییس خود آماده و ارایه کنید. بنابراین برای نوشتن گزارش، زمانی را مانند آخرین هفته‌ی ماه، درنظر می‌گیرید. به این ترتیب هرگاه مشغول انجام کار دیگری هستید و ناگهان فکر نوشتن گزارش به شما هجوم می‌آورد، می‌دانید که برای انجام این کار زمان خاصی تعیین شده‌است و آن را در زمان مناسب انجام خواهید داد. بدین ترتیب، آرامش فکری خود را  باز می‌گردانید.

4) دسته چهارم  کارهایی هستند که در حقیقت می‌توانند توسط افراد دیگری انجام شوند. بنابراین آنها را واگذار کنید. توجه کنید که واگذار کردن کارها باید با مهارت انجام شود. بدین معنی که فرد موردنظر باید تخصص و انگیزه انجام  آن کار را داشته باشد. به طورمثال، اگر شما سرپرست یک تیم در محیط کار خود هستید، کارها را با مهارت به اعضای گروه اختصاص دهید؛ به جای اینکه سعی کنید خودتان همه کارها را انجام دهید.

سؤالات زیر را در نظر بگیرید:

1- چه دستاوردی را می‌خواهید داشته باشید؟

2- آیا واقعا مهم است؟

3- چقدر مهم است؟

4- به انجام رساندن این کار چه تاثیر یا نتایجی خواهد داشت؟

5- بهترین کاری که می‌توانید الان انجام دهید چیست؟

6- آیا حتما باید توسط من انجام گیرد؟

7- و...

این‌ها نمونه سؤالاتی هستند که می‌توانید در زمان دسته بندی کردن کارها از خود بپرسید. سؤالاتی از این قبیل شما را راهنمایی می‌کنند تا دسته بندی کارها را با مهارت بیشتر و بهتری انجام دهید.

بعد از دسته بندی کارها، حالا لیستی از کارهایی را دارید که هم اکنون زمان انجام آنها فرا رسیده است. آنها را توسط سیستم اولویت بندی چابک، اولویت بندی نمایید و 3 تا از بایدهای لیست را به عنوان دیدگاه هفتگی و یا خروجی روزانه انتخاب کنید.  

مطالب
مروری بر پلاگین‌های چندسکویی مرورگرها
NPAPI
این عبارت مخفف Netscape Plugin Application Programming Interface هست و یک پلاگین چندسکویی است که بسیاری از مرورگرها از آن استفاده می‌کنند. معماری این پلاگین ابتدا در سال 1995 برای مرورگر netscape نسخه 2 آن توسعه پیدا کرد. ولی رفته رفته توسط دیگر مرورگرها هم استفاده و پیاده سازی شد و البته تعدادی هم بعدها استفاده از آن را رها کردند و از فناوری‌های دیگری استفاده کردند.
کار این پلاگین تعریف یک سری ContentType مانند audio/mp3 است و موقعی‌که مرورگر در رندر کردن این صفحات به چنین محتوایی برخورد کند، پلاگین مربوط به این محتوا را در حافظه بار می‌کند تا پلاگین را در حافظه رندر کرده و جابجایی داده‌ها با پلاگین صورت بگیرد. سپس آن پلاگین محتوای مربوطه را رندر می‌کند. امروزه پلاگین‌ها در همان قسمت از حافظه صفحه مرورگر بار می‌شوند و مانند مرورگرهای قدیمی مجبور به اجرای برنامه خارجی برای محتواهای ناشناخته نیستند.
این API نیاز دارد هر پلاگین تقریبا 15 تابع را پیاده سازی کند. این توابع برای پیاده سازی، ایجاد، نابودسازی آن و موقعیت مکانی آن به کار می‌روند. NPAPI همچنین امکاناتی از قبیل اسکریت نویسی، چاپ کردن، تمام صفحه شدن، پلاگین بدون پنجره، استریم کردن محتوا را نیز دارد.
مبداء و منشا ابتدایی این فناوری از شرکت Adobe و محصول Adobe Reader آن و خواندن PDF‌های تحت وب آغاز گشت. در آن زمان در وب، تنها فرمت HTML به همراه تصاویر به عنوان محتوا حساب میشد و مابقی نوع‌ها به دانلود ختم می‌شدند و شرکت ادوب قصد داشت کاربران تجربه‌ی جدیدی از خواندن فایل‌های PDF را بر روی مرورگر وب داشته باشند و برای دیدن حتما نیازی به دانلود نداشته باشند.
شرکت ادوب برای جلب نظر توسعه دهنگان netscape از یک نسخه‌ی دمو استفاده کرد و موقعی که روی لینک یک PDF کلیک میشد به جای دانلود آن، محتوا داخل صفحه مرورگر رندر میشد که مخلوطی از کدهای html و PDF بود ولی آن‌ها خواستار یک سیستم یکپارچه بودند تا دیگر مرورگر netscape درگیر آن نباشد و بدون وابستگی به مرورگر و به طور مستقل این کار انجام شود که کم کم باعث ایجاد این API شد و از آن موقع در طول این سال‌ها مرورگرهای زیادی از این فناوری استفاده کردند تا استاندارد عمومی در توسعه مرورگرها باشد.

عدم پشتیبانی گوگل از این پلاگین API
گوگل در سال 2013 عدم پشتیبانی از این API را در مرورگرش اعلام کرد که در این حالت پشتیبانی از تمامی فناوری‌های مرتبط آن نیز خاتمه میابد که شامل جاوا و سیلورلایت می‌شود و دلیل آن مسائل پایداری و امنیت آن در کنار سایر موارد است.

پشتیبانی از اسکریپت نویسی
این ویژگی اجازه میدهد که شما با استفاده از کدهای جاوااسکریپت، در صفحات وب با پلاگین تعامل کنید. ابتدا netscape این امکان را اضافه کرد و بعدها موزیلا این ویژگی را با استفاده از فناوری هایی چون Live Connect ،  XP Connect و npRuntime ارتقاء بخشید.

Live Connect
از netscape 4 به بعد NPAPI برای اسکریپت نویسی توسعه یافت. این ویژگی به مرورگرها اجازه میدهد که برنامه‌های نوشته شده با جاوا و جاوااسکریپت، با صفحات وب به تعامل بپردازند. به عنوان مثال اپلت نوشته شده با جاوا می‌تواند با کدهای داخل صفحه ارتباط برقرار کند یا بیشتر از خود اسکریت‌های صفحه با محیط جاوااسکریت داخلی ارتباط برقرار کند.  با این ویژگی یک پلاگین میتواند یک نمونه کلاس جاوا را پیاده سازی و بازگرداند. این کلاس میتواند از طریق جاوااسکریت یا اپلت‌های جاوا صدا زده شود.

XP Connect
ابتدا قبل از هر چیز بگذارید با XPCOM اشنا شویم. XPCOM یا Cross Platform Component Object Model از طرف شرکت موزیلا ارائه شده است و اصلی‌ترین ویژگی آن اتصال چندین زبان به یکدیگر از طریق IDL یا یک زبان واسط است. بدین ترتیب برنامه نویس‌ها میتوانستند کدهای اختصاصی خود را با دیگر کامپوننت‌ها مرتبط کنند.
حال کار xpconnect برقراری ارتباط بین جاوااسکریپت با XPCOM یا کدهای نوشته شده توسعه گران است. XP Connect به اشیاء جاوااسکریپتی اجازه می‌دهد به طور مستقیم به اشیاء XPCom دسترسی داشته و آن‌ها را دستکاری کنند.

NPRuntime
در پایان سال 2004 بسیاری از شرکت‌های اصلی ارائه کننده مرورگرهای وب که از NPAPI استفاده می‌کردند، به این توافق رسیدند که از فناوری NPRuntime به عنوان یک اکستنشن (افزونه) برای تامین اسکریپت نویسی NPAPI استفاده کنند. اسکریپت نویسی این فناوری مستقل از دیگر فناوری‌هایی چون جاوا و XPCOM است و توسط گوگل (در آن زمان)، فایرفاکس، سافاری و اپرا (در آن زمان)  پشتیبانی می‌شود.

PPAPI
این فناوری در 12 آگوست 2009 معرفی شد. Pepper Plugin API مجموعه ای از تغییرات و اصلاحات روی NPAPI است که باعث انعطاف پذیری و امنیت بیشتر می‌شود. این افزونه جهت پیاده سازی آسان اجرای پلاگین در یک پروسه‌ی جداگانه است. هدف این پروژه تهیه یک فریمورک برای ایجاد پلاگین‌های مستقل یا Cross-Platform میباشد.
تعدادی از مواردی که در طراحی این افزونه در نظر گرفته شده است:
  • اجرای جداگانه از پروسه‌ی مرورگر
  • تعریف رویدادهای استاندارد و رسم تصاویر دو بعدی
  • تهیه گرافیک سه بعدی
  • ریجستری پلاگین
  • استاندارد سازی برای استفاده از سیستم رندر مرورگر Compositing Process 
  • تعریف مفهوم یا معنای واحد از NPAPI بین تمامی مروگرها
مرورگرهایی که در حال حاضر به این افزونه روی آورده اند طبعا مرورگر کروم و اپرا از نسخه 24 به بعد است.
شرکت موزیلا در سال 2011 اعلام کرد که فعلا علاقه ای به شرکت در این پروژه ندارد.
شرکت ادوب برای افزونه flash player اعلام کرد که دیگر تنها بر روی PPAPI فعالیت می‌کنند و از آخرین نسخه فلش پلیر 11.2 که برای NPAPI ایجاد شده است تنها به مدت پنج سال بسته‌های آپدیت آن را در دسترس قرار میدهد.

ActiveX
یکی دیگر از این پلاگین‌ها ActiveX است که توسط IE مورد استفاده قرار می‌گیرد ولی در مرورگر Edge  حذف شده است. به این دلیل، پشتیبانی از جاوا در این مرورگر قطع شده است و فلش پلیر را به صورت ذاخلی Built-in پشتیبانی می‌کند. امروزه بسیاری از تولیدکنندگان اعتقاد دارند که با Html5 بسیاری از مسائل حل می‌شود.
مطالب دوره‌ها
چرا XML و چرا پشتیبانی توکار از آن در SQL Server
مقدمه

فیلدهای XML از سال 2005 به امکانات توکار SQL Server اضافه شده‌اند و بسیاری از مزایای دنیای NoSQL را درون SQL Server رابطه‌ای مهیا می‌سازند. برای مثال با تعریف یک فیلد به صورت XML، می‌توان از هر ردیف به ردیفی دیگر، اطلاعات متفاوتی را ذخیره کرد؛ به این ترتیب امکان کار با یک فیلد که می‌تواند اطلاعات یک شیء را قبول کند و در حقیقت امکان تعریف اسکیمای پویا و متغیر را در کنار امکانات یک بانک اطلاعاتی رابطه‌ای که از اسکیمای ثابت پشتیبانی می‌کند، میسر می‌شود.
همچنین SQL Server در این حالت قابلیتی را ارائه می‌دهد که در بسیاری از بانک‌های اطلاعاتی NoSQL میسر نیست. در اینجا در صورت نیاز و لزوم می‌توان اسکیمای کاملا مشخصی را به یک فیلد XML نیز انتساب داد؛ هر چند این مورد اختیاری است و می‌توان یک un typed XML را نیز بکار برد. به علاوه امکانات کوئری گرفتن توکار از این اطلاعات را به کمک XPath ترکیب شده با T-SQL، نیز فراموش نکنید.
بنابراین اگر یکی از اهداف اصلی گرایش شما به سمت دنیای NoSQL، استفاده از امکان تعریف اطلاعاتی با اسکیمای متغیر و پویا است، فیلدهای نوع XML اس کیوال سرور را مدنظر داشته باشید.
یک مثال عملی: فناوری Azure Dev Fabric's Table Storage (نسخه Developer ویندوز Azure که روی ویندوزهای معمولی اجرا می‌شود؛ یک شبیه ساز خانگی) به کمک SQL Server و فیلدهای XML آن طراحی شده است.



چرا XML و چرا پشتیبانی توکار از آن در SQL Server

یک سند XML معمولا بیشتر از یک قطعه داده را در خود نگهداری می‌کند و نوع داده‌ی پیچیده محسوب می‌شود؛ برخلاف داده‌هایی مانند int یا varchar که نوع‌هایی ساده بوده و تنها یک قطعه از اطلاعات خاصی را در خود نگهداری می‌کنند. بنابراین شاید این سؤال مطرح شود که چرا از این نوع داده پیچیده در SQL Server پشتیبانی شده‌است؟
- از سال‌های نسبتا دور، از XML برای انتقال داده‌ها بین سیستم‌ها و سکوهای کاری مختلف استفاده شده‌است.
- استفاده‌ی گسترده‌ای در برنامه‌های تجاری دارد.
- بسیاری از فناوری‌های موجود از آن پشتیبانی می‌کنند.
برای مثال اگر با فناوری‌های مایکروسافتی کار کرده باشید، به طور قطع حداقل در یک یا چند قسمت از آن‌ها، مستقیما از XML استفاده شده‌است.
بنابراین با توجه به اهمیت و گستردگی استفاده از آن، بهتر است پشتیبانی توکاری نیز از آن داخل موتور یک بانک اطلاعاتی، پیاده سازی شده باشد. این مساله سهولت تهیه پشتیبان‌های خودکار، بازیابی آن‌ها و امنیت یکپارچه با SQL Server را به همراه خواهد داشت؛ به همراه تمام زیرساخت‌های مهیای در SQL Server.



روش‌های مختلف ذخیره سازی XML در بانک‌های اطلاعاتی رابطه‌ای

الف) ذخیره سازی متنی
این روش نیاز به نگارش خاصی از SQL Server یا بانک اطلاعاتی الزاما خاصی نداشته و با تمام بانک‌های اطلاعاتی رابطه‌ای سازگار است؛ مثلا از فیلدهای varchar برای ذخیره سازی آن استفاده شود. مشکلی که این روش به همراه خواهد داشت، از دست دادن ارزش یک سند XML و برخورد متنی با آن است. زیرا در این حالت برای تعیین اعتبار آن یا کوئری گرفتن از آن‌ها نیاز است اطلاعات را از بانک اطلاعاتی خارج کرده و در لایه‌ای دیگر از برنامه، کار جستجو پردازش آن‌ها را انجام داد.

ب) تجزیه XML به چندین جدول رابطه‌ای
برای مثال یک سند XML را درنظر بگیرید که دارای اطلاعات شخص و خرید‌های او است. می‌توان این سند را به چندین فیلد در چندین جدول مختلف رابطه‌ای تجزیه کرد و سپس با روش‌های متداول کار با بانک‌های اطلاعاتی رابطه‌ای از آن‌ها استفاده نمود.

ج) ذخیره سازی آن‌ها توسط فیلدهای خاص XML
در این حالت با استفاده از فیلدهای ویژه XML می‌توان از فناوری‌های مرتبط با XML تمام و کمال استفاده کرد. برای مثال تهیه کوئری‌های پیچیده داخل همان بانک اطلاعاتی بدون نیاز به تجزیه سند به چندین جدول و یا خارج کردن آن‌ها از بانک اطلاعاتی و جستجوی بر روی آن‌ها در لایه‌ای دیگر از برنامه.


موارد کاربرد XML در SQL Server

کاربردهای مناسب

- اطلاعات، سلسله مراتبی و تو در تو هستند. XQuery و XPath در این موارد بسیار خوب عمل می‌کند.
- ساختار قسمتی از اطلاعات ثابت است و قسمتی از آن خیر. برای نمونه، یک برنامه‌ی فرم ساز را درنظر بگیرید که هر فرم آن هر چند دارای یک سری خواص ثابت مانند نام، گروه و امثال آن است، اما هر کدام دارای فیلدهای تشکیل دهنده متفاوتی نیز می‌باشد. به این ترتیب با استفاده از یک فیلد XML، دیگری نیازی به نگران بودن در مورد نحوه مدیریت اسکیمای متغیر مورد نیاز، نخواهد بود.
نمونه‌ی دیگر آن ذخیره سازی خواص متغیر اشیاء است. هر شیء دارای یک سری خواص ثابت است اما خواص توصیف کننده‌ی آن‌ها از هر رکورد به رکوردی دیگر متفاوت است.

کاربردهای نامناسب

- کل اطلاعات را داخل فیلد XML قرار دادن. هدف از فیلدهای XML قرار دادن یک دیتابیس داخل یک سلول نیست.
- ساختار تعریف شده کاملا مشخص بوده و به این زودی‌ها هم قرار نیست تغییر کند. در این حالت استفاده از قابلیت‌های رابطه‌ای متداول SQL Server مناسب‌تر است.
- قرار دادن اطلاعات باینری بسیار حجیم در سلول‌های XML ایی.
 


تاریخچه‌ی پشتیبانی از XML در نگارش‌های مختلف SQL Server

الف) SQL Server 2000
در SQL Server 2000 روش (ب) توضیح داده شده در قسمت قبل، پشتیبانی می‌شود. در آن برای تجزیه یک سند XML به معادل رابطه‌ای آن، از تابعی به نام OpenXML استفاده می‌شود و برای تبدیل این اطلاعات به XML از روش Select … for XML می‌توان کمک گرفت. همچنین تاحدودی مباحث XPath Queries نیز در آن گنجانده شد‌ه‌است.

ب) SQL Server 2005
در نگارش 2005 آن، برای اولین بار نوع داده‌ای ویژه XML معرفی گشت به همراه امکان تعریف اسکیمای XML و اعتبارسنجی آن و پشتیبانی از XQuery برای جستجوی سریع بر روی داده‌های XML داخل همان بانک اطلاعاتی، بدون نیاز به استخراج اطلاعات XML و پردازش مجزای آن‌ها در لایه‌ای دیگر از برنامه.

ج) SQL Server 2008 به بعد
در اینجا فاز نگهداری این نوع داده خاص شروع شده و بیشتر شامل یک سری بهبودهای کوچک در کارآیی و نحوه‌ی استفاده از آن‌ها می‌شود.



استفاده از XML با کمک SQLCLR

از SQL Server 2005 به بعد، امکان استفاده از کلیه‌ی امکانات موجود در فضای نام System.Xml دات نت، در SQL Server نیز به کمک SQL CLR مهیا شده‌است. همچنین از SQL Server 2008 به بعد، امکانات فضای نام System.Xml.Linq و مباحث LINQ to XML نیز توسط SQL CLR پشتیبانی می‌شوند.
البته این امکانات در SQL Server 2005 نیز قابل استفاده هستند، اما اسمبلی شما unsafe تلقی می‌شود. پس از آزمایشات و بررسی کافی، فضای نام مرتبط با LINQ to XML و امکانات آن، به عنوان اسمبلی‌هایی امن و قابل استفاده در SQL Server 2008 به بعد، معرفی شده‌اند.




مزایای وجود فیلد ویژه XML در SQL Server

پس از اینکه فیلدهای XML به صورت یک نوع داده بومی بانک اطلاعاتی SQL Server معرفی شدند، مزایای ذیل بلافاصله در اختیار برنامه نویس‌ها قرار گرفت:
- امکان تعریف آن‌ها به صورت یک ستون جدولی خاصی
- استفاده از آن‌ها به عنوان یک پارامتر رویه‌های ذخیره شده
- امکان تعریف خروجی توابع scalar سفارشی تعریف شده به صورت XML
- امکان تعریف متغیرهای T-SQL از نوع XML

برای مثال در اینجا نحوه‌ی تعریف یک جدول جدید دارای فیلدی از نوع XML را مشاهده می‌کنید:
 CREATE TABLE xml_tab
(
  id INT,
  xml_col  XML
)
- پشتیبانی از فناوری‌های XML ایی مانند اعتبارسنجی اسکیما و نوشتن کوئری‌های پیشرفته با XQuery و XPath.
- امکان تعریف ایندکس‌های XML ایی اضافه شده‌است.



چه نوع XML ایی را می‌توان در فیلدهای XML ذخیره کرد؟

فیلدهای XML امکان ذخیره سازی داده‌های XML خوش فرم را مطابق استاندارد یک XML، دارند. حداکثر اندازه قابل ذخیره سازی در یک فیلد XML دو گیگابایت است.
البته امکانات مهیای در SQL Server در بسیاری از موارد فراتر از استاندارد یک XML هستند. به این معنا که در فیلدهای XML می‌توان Documents و یا Fragments را ذخیره سازی کرد. یک سند XML یا Document حاوی تنها یک ریشه اصلی است؛ اما یک Fragment می‌تواند بیش از یک ریشه اصلی را در خود ذخیره کند. یک مثال:
 DECLARE @xml_tab TABLE (xml_col XML)
-- document
INSERT @xml_tab VALUES ('<person/>')
-- fragment
INSERT @xml_tab VALUES ('<person/><person/>')
SELECT * FROM @xml_tab
مدل داده‌ای XML در SQL Server بر مبنای استانداردهای  XQuery و XPath طراحی شده‌است و این استانداردها Fragments را به عنوان یک قطعه داده XML معتبر، قابل پردازش می‌دانند؛ علاوه بر آن مقادیر null و خالی را نیز معتبر می‌دانند. برای مثال عبارات ذیل معتبر هستند:
 DECLARE @xml_tab TABLE (xml_col XML)
-- text only
INSERT @xml_tab VALUES ('data data data .....')
-- empty string
INSERT @xml_tab VALUES ('')
-- null value
INSERT @xml_tab VALUES (null)
SELECT * FROM @xml_tab
همچنین امکان ذخیره سازی یک متن خالی بدون فرمت نیز در اینجا مجاز است. بنابراین به کمک T-SQL می‌توان برای مثال نوع داده varchar و varchar max را به XML تبدیل کرد و برعکس. امکان تبدیل Text و NText (منسوخ شده) نیز به XML وجود دارد ولی در این حالت خاص، عکس آن، پشتیبانی نمی‌شود.
به علاوه باید دقت داشت که در SQL Server نوع داده‌ای XML برای ذخیره سازی داده‌ها بکار گرفته می‌شود. به این معنا که در اینجا پیشوندهای فضاهای نام XML بی‌معنا هستند.
 DECLARE @xml_tab TABLE (xml_col XML)
INSERT @xml_tab VALUES ('<doc/>')
INSERT @xml_tab VALUES ('<doc xmlns="http://www.doctors.com"/>')
-- این سه سطر در عمل یکی هستند
INSERT @xml_tab VALUES ('<doc xmlns="http://www.documents.com"/>')
INSERT @xml_tab VALUES ('<dd:doc xmlns:dd="http://www.documents.com"/>')
INSERT @xml_tab VALUES ('<rr:doc xmlns:rr="http://www.documents.com"/>')
SELECT * FROM @xml_tab
در این مثال، سه insert آخر در عمل یکی درنظر گرفته می‌شوند.



Encoding ذخیره سازی داده‌های XML

SQL Server امکان ذخیره سازی اطلاعات متنی را به فرمت UFT8، اسکی و غیره، دارد. اما جهت پردازش فیلدهای XML و ذخیره سازی آن‌ها از Collation پیش فرض بانک اطلاعاتی کمک خواهد گرفت. البته ذخیره سازی نهایی آن همیشه با فرمت UCS2 است (یونیکد دو بایتی).
 DECLARE @xml_tab TABLE  (id INT, xml_col XML)

INSERT INTO @xml_tab
VALUES
  (
5,
N'<?xml version="1.0" encoding="utf-8"?>
<doc1>
  <row name="vahid"></row>
</doc1>
')
برای نمونه به مثال فوق دقت کنید. اگر آن‌را اجرا کنید، برنامه با خطای ذیل متوقف خواهد شد:
 XML parsing: line 1, character 38, unable to switch the encoding
علت اینجا است که با قرار دادن N در ابتدای رشته XML ایی در حال ذخیره سازی، آن‌را به صورت یونیکد دوبایتی معرفی کرده‌ایم اما encoding سند در حال ذخیره سازی utf-8 تعریف شده‌است و این‌دو با هم سازگاری ندارند.
برای حل این مشکل باید N ابتدای رشته را حذف کرد. روش دوم، معرفی و استفاده از utf-16 است بجای utf-8 در ویژگی encoding.
همچنین در این حالت اگر encoding را utf-16 معرفی کنیم و ابتدای رشته در حال ذخیره سازی N قرار نگیرد، باز با خطای unable to switch the encoding مواجه خواهیم شد.



نحوه‌ی ذخیره سازی اطلاعات XML ایی در SQL Server

SQL Server فرمت اطلاعات XML وارد شده را حفظ نمی‌کند. برای مثال اگر قطعه کد زیر را اجرا کنید
 DECLARE @xml_tab TABLE  (id INT, xml_col XML)

INSERT INTO @xml_tab
VALUES
  (
5,
'<?xml version="1.0" encoding="utf-8"?><doc1><row name="vahid"></row></doc1>'
  )
   
SELECT * FROM @xml_tab
خروجی Select انجام شده به صورت زیر است:
 <doc1>
  <row name="vahid" />
</doc1>
اطلاعات و داده نهایی، بدون تغییری از آن قابل استخرج است. اما اصطلاحا lexical integrity آن حفظ نشده و نمی‌شود. بنابراین در اینجا ذکر سطر xml version ضروری نیست و یا برای مثال اگر ویژگی‌ها را توسط " و یا ' مقدار دهی کنید، همیشه توسط "  ذخیره خواهد شد.



ذخیره سازی داده‌هایی حاوی کاراکترهای غیرمجاز XML

اطلاعات دنیای واقعی همیشه به همراه اطلاعات تک کلمه‌ای ساده نیست. ممکن است نیاز شود انواع و اقسام حروف و تگ‌ها نیز در این بین به عنوان داده ذخیره شوند. روش حل استاندارد آن بدون نیاز به دستکاری اطلاعات ورودی، استفاده از CDATA است:
 DECLARE @xml_tab TABLE  (id INT, xml_col XML)

INSERT INTO @xml_tab
VALUES
  (
5,
'<person><![CDATA[ 3 > 2 ]]></person>'
  )
   
SELECT * FROM @xml_tab
در این حالت خروجی select اطلاعات ذخیره شده به صورت زیر خواهد بود:
 <person> 3 &gt; 2 </person>
به صورت خودکار قسمت CDATA پردازش شده و اصطلاحا حروف غیرمجاز XML ایی به صورت خودکار escape شده‌اند.



محدودیت‌های فیلدهای XML

- امکان مقایسه مستقیم را ندارند؛ بجز مقایسه با نال. البته می‌توان XML را تبدیل به مثلا varchar کرد و سپس این داده رشته‌ای را مقایسه نمود. برای مقایسه با null توابع isnull و coalesce نیز قابل بکارگیری هستند.
- order by و group by بر روی این فیلدها پشتیبانی نمی‌شود.
- به عنوان ستون کلید قابل تعریف نیست.
- به صورت منحصربفرد و unique نیز قابل علامتگذاری و تعریف نیست.
- فیلدهای XML نمی‌توانند دارای collate باشند.
نظرات مطالب
Blazor 5x - قسمت 33 - احراز هویت و اعتبارسنجی کاربران Blazor WASM - بخش 3- بهبود تجربه‌ی کاربری عدم دسترسی‌ها
یک نکته‌ی تکمیلی: کار با Policy‌ها در برنامه‌های Blazor WASM

در این مطلب، روشی را برای برقراری دسترسی نقش Admin، به تمام قسمت‌های محافظت شده‌ی برنامه، با معرفی نقش آن به یک ویژگی Authorize سفارشی شده، مشاهده کردید. هرچند این روش کار می‌کند، اما روش جدیدتر برقراری یک چنین دسترسی‌های ترکیبی در برنامه‌های ASP.NET Core و سایر فناوری‌های مشتق شده‌ی از آن، کار با Policyها است که برای نمونه در مثال فوق، به صورت زیر قابل پیاده سازی است:

الف) تعریف Policyهای مشترک بین برنامه‌های Web API و WASM
Policyهای تعریف شده، باید قابلیت اعمال به اکشن متدهای کنترلرها و همچنین کامپوننت‌های WASM را داشته باشند. به همین جهت آن‌ها را در پروژه‌ی اشتراکی BlazorServer.Common که در هر دو پروژه استفاده می‌شود، قرار می‌دهیم:
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization; // dotnet add package Microsoft.AspNetCore.Authorization

namespace BlazorServer.Common
{
    public static class PolicyTypes
    {
        public const string RequireAdmin = nameof(RequireAdmin);
        public const string RequireCustomer = nameof(RequireCustomer);
        public const string RequireEmployee = nameof(RequireEmployee);
        public const string RequireEmployeeOrCustomer = nameof(RequireEmployeeOrCustomer);

        public static AuthorizationOptions AddAppPolicies(this AuthorizationOptions options)
        {
            options.AddPolicy(RequireAdmin, policy => policy.RequireRole(ConstantRoles.Admin));
            options.AddPolicy(RequireCustomer, policy =>
                    policy.RequireAssertion(context =>
                        context.User.HasClaim(claim => claim.Type == ClaimTypes.Role
                            && (claim.Value == ConstantRoles.Admin || claim.Value == ConstantRoles.Customer))
                    ));
            options.AddPolicy(RequireEmployee, policy =>
                    policy.RequireAssertion(context =>
                        context.User.HasClaim(claim => claim.Type == ClaimTypes.Role
                            && (claim.Value == ConstantRoles.Admin || claim.Value == ConstantRoles.Employee))
                    ));

            options.AddPolicy(RequireEmployeeOrCustomer, policy =>
                                policy.RequireAssertion(context =>
                                    context.User.HasClaim(claim => claim.Type == ClaimTypes.Role
                                        && (claim.Value == ConstantRoles.Admin ||
                                            claim.Value == ConstantRoles.Employee ||
                                            claim.Value == ConstantRoles.Customer))
                                ));
            return options;
        }
    }
}
در اینجا یکسری Policy جدید را مشاهده می‌کنید که در آن‌ها همواره نقش Admin حضور دارد و همچین روش or آن‌ها را توسط policy.RequireAssertion مشاهده می‌کنید. این تعاریف، نیاز به نصب بسته‌ی Microsoft.AspNetCore.Authorization را نیز دارند. با کمک Policyها می‌توان ترکیب‌های پیچیده‌ای از دسترسی‌های موردنیاز را ساخت؛ بدون اینکه نیاز باشد مدام AuthorizeAttribute سفارشی را طراحی کرد.

ب) افزودن Policyهای تعریف شده به پروژه‌های Web API و WASM
پس از تعریف Policyهای مورد نیاز، اکنون نوبت به افزودن آن‌ها به برنامه‌های Web API:
namespace BlazorWasm.WebApi
{
    public class Startup
    {
        // ...

        public void ConfigureServices(IServiceCollection services)
        {
            // ...

            services.AddAuthorization(options => options.AddAppPolicies());

            // ...
و همچنین WASM است:
namespace BlazorWasm.Client
{
    public class Program
    {
        public static async Task Main(string[] args)
        {
            // ...

            builder.Services.AddAuthorizationCore(options => options.AddAppPolicies());

            // ...
        }
    }
}
به این ترتیب Policyهای یک‌دستی را بین برنامه‌های کلاینت و سرور، به اشتراک گذاشته‌ایم.

ج) استفاده از Policyهای تعریف شده در برنامه‌ی WASM
اکنون که برنامه قابلیت کار با Policyها را پیدا کرده، می‌توان فیلتر Roles سفارشی را حذف و با فیلتر Authorize پالیسی دار جایگزین کرد:
@page "/hotel-room-details/{Id:int}"

// ...

@*
@attribute [Roles(ConstantRoles.Customer, ConstantRoles.Employee)]
*@

@attribute [Authorize(Policy = PolicyTypes.RequireEmployeeOrCustomer)]

حتی می‌توان از پالیسی‌ها در حین تعریف AuthorizeViewها نیز استفاده کرد:
<AuthorizeView  Policy="@PolicyTypes.RequireEmployeeOrCustomer">
    <p>You can only see this if you're an admin or an employee or a customer.</p>
</AuthorizeView>
مطالب
بررسی تغییرات Blazor 8x - قسمت سیزدهم - امکان تعریف Sections
اگر پیشتر با فناوری‌های مرتبط با خانواده‌ی ASP.NET کار کرده باشید، با مفاهیمی مانند ContentPlaceHolder در وب‌فرم‌ها و یا RenderSection در ASP.NET MVC، برخورد داشته‌اید. دقیقا یک چنین قابلیتی نیز به Blazor 8x تحت عنوان Sections اضافه شده‌است تا توسط آن بتوان محتوای قسمتی از قالب کلی صفحه را از طریق زیر کامپوننت‌های آن تغییر داد و کنترل کرد.


کامپوننت‌های جدید SectionOutlet و SectionContent در Blazor 8x

پیاده سازی Sections در Blazor 8x به کمک دو کامپوننت جدید SectionOutlet و SectionContent میسر شده‌است و برای دسترسی به آن‌ها نیاز است ابتدا به فایل Imports.razor_ پروژه، مراجعه کرد و using زیر را به آن اضافه نمود تا این اشیاء، در کامپوننت‌های برنامه قابل شناسایی و استفاده شوند:
@using Microsoft.AspNetCore.Components.Sections

SectionOutlet کامپوننتی است که محتوای ارائه شده‌ی توسط کامپوننت SectionContent را رندر می‌کند (این محتوا در اصل یک RenderFragment است). ارتباط بین این دو هم توسط خواص SectionName و یا SectionId‌های متناظر، برقرار می‌شود. اگر چندین SectionContent دارای نام و یا Id یکسانی باشند، محتوای آخرین آن‌ها در SectionOutlet متناظر، رندر می‌شود.

برای مثال در فایل MainLayout.razor، تغییر زیر را اعمال می‌کنیم:
<div class="top-row px-4">
    <SectionOutlet SectionName="before-top-row"/>
    <a href="https://learn.microsoft.com/aspnet/core/" target="_blank">About</a>
</div>
که در آن یک SectionOutlet، با نام before-top-row اضافه شده‌است و سبب درج محتوایی پیش از لینک About می‌شود. پس از این تعریف، اکنون در هر کامپوننتی از برنامه می‌توان محتوای این قسمت را به نحو زیر تامین کرد:
<SectionContent SectionName="before-top-row">
    <a href="/show-help" target="_blank">Help</a>
</SectionContent>
همانطور که مشخص است، این محتوا بر اساس نام ذکر شده‌ی متناظر با نام SectionOutlet، با آن ارتباط برقرار می‌کند.


روش تعریف یک محتوای پیش‌فرض

این محتوا، فقط زمانی تامین خواهد شد که کامپوننت در حال نمایش SectionContent، قابل مشاهده و فعال شده باشد. یعنی اگر از کامپوننت نمایش دهنده‌ی آن به صفحه‌ی دیگری رجوع کنیم، محتوای SectionOutlet مجددا خالی خواهد شد، تا زمانیکه به آدرس نمایش دهنده‌ی کامپوننت دربرگیرنده‌ی SectionContent متناظر با آن رجوع کنیم. به همین جهت اگر علاقمند به نمایش یک «محتوای پیش‌فرض» هستید، می‌توان به صورت زیر عمل کرد:
<div class="top-row px-4">
    <SectionOutlet SectionName="before-top-row" />
    <SectionContent SectionName="before-top-row">
        <a href="https://learn.microsoft.com/aspnet/core/" target="_blank">About</a>
    </SectionContent>
</div>
به این ترتیب حتی اگر در لحظه‌ی نمایش کامپوننت جاری، هیچ SectionContent متناظری یافت نشد، از همان SectionContent ذیل این SectionOutlet، برای تامین محتوای آن استفاده می‌شود و اگر کامپوننتی محتوای جدیدی را تعریف کرد، چون همیشه آخرین SectionContent رندر شده، محتوای نهایی را تامین می‌کند، این محتوای جدید، جایگزین نمونه‌ی پیش‌فرض خواهد شد.


تفاوت SectionId با SectionName

کامپوننت SectionOutlet، هم می‌تواند یک SectionName را دریافت کند و هم یک SectionId را. SectionNameها، رشته‌ای هستند و تغییرات آتی آن‌ها تحت نظارت کامپایلر نیست. به همین جهت اگر نیاز به Refactoring آن‌ها است، شاید بهتر باشد از خاصیت SectionId که یک Id از نوع strongly typed را مشخص می‌کند، استفاده کنیم.
برای نمونه می‌توان مثال قبلی را به صورت زیر با استفاده از یک SectionId، بازنویسی کرد:
<div class="top-row px-4">
    <SectionOutlet SectionId="BeforeTopRow" />
    <a href="https://learn.microsoft.com/aspnet/core/" target="_blank">About</a>
</div>

@code{

    public static SectionOutlet BeforeTopRow = new(); 
}
که در اینجا SectionId، یک فیلد استاتیک از نوع SectionOutlet است.
سپس هر کامپوننت دیگری که بخواهد از این Id استاتیک استفاده کند، روش کار آن به صورت زیر است:
<SectionContent SectionId="MainLayout.BeforeTopRow">
    <a href="/show-help" target="_blank">Help</a>
</SectionContent>
مطالب
فشرده سازی اطلاعات در SQL server 2008

علاوه بر فشرده سازی خودکار بک آپ‌ها که پیشتر در مورد آن‌ها صحبت شد، اس کیوال سرور 2008 دو نوع فشرده سازی دیگر را نیز پشتیبانی می‌کند:

Row Compression :

حالت row compression نحوه‌ی ذخیره سازی فیزیکی داده‌ها را تغییر می‌دهد. فعال سازی آن اثرات زیر را خواهد داشت:
الف) متادیتای هر رکورد را حداقل می‌کند (منظور از متادیتا اطلاعاتی مانند اطلاعات ستون‌ها، طول و آفست و غیره است)
ب) داده‌های عددی و رشته‌هایی با طول ثابت، به صورت اطلاعاتی با طول متغیر ذخیره خواهند شد، درست مانند varchar ها.

برای ایجاد جدولی که row compression در آن به صورت پیش‌فرض فعال است، می‌توان مانند مثال زیر عمل کرد:
CREATE TABLE MyTable
(
ID int identity Primary key,
Name char(100),
Email char(100)
)
WITH (DATA_COMPRESSION = Row);

GO
و اگر جدول موجودی را می‌خواهید تغییر داده و این خاصیت را بر روی آن فعال نمائید، روش زیر را اعمال کنید:
Alter TABLE MyTable REBUILD WITH (DATA_COMPRESSION=Row, MAXDOP=2);
در اینجا MAXDOP مشخص می‌کند که از چند CPU باید برای فشرده سازی استفاده شود. (اگر جدولی حجیم دارید، به این صورت می‌توان عملیات فشرده سازی را سریعتر به پایان رساند)


Page Compression :

در روش دوم فشرده سازی اطلاعات در اس‌کیوال سرور 2008 ، که مهم‌ترین حالت موجود نیز می‌باشد، اطلاعات مشترک، بین سطرهای یک صفحه به اشتراک گذاشته می‌شوند. این روش از فناوری‌های زیر استفاده می‌کند:
الف) روش row compression که در مورد آن صحبت شد جزئی از این روش است.
ب) Prefix Compression : به ازای هر ستون در یک صفحه، Prefix های تکراری یافت شده و در هدر مخصوص فشرده سازی ذخیره می‌شوند (محل این هدر پس از هدر صفحه است). سپس هرجایی که به این Prefix ها اشاره شده‌باشد، عدد منحصربفرد شناسایی کننده آن‌ها نسبت داده می‌شود.
ج) Dictionary Compression : در این حالت مقادیر تکراری یک صفحه جستجو شده و در هدر فشرده سازی صفحه ذخیره می‌شوند. حالت Prefix Compression فقط به یک ستون منحصر می‌شود اما Dictionary Compression به کل صفحه اعمال می‌گردد.

برای فعال سازی آن در یک جدول جدید به روش زیر می‌توان عمل نمود:
CREATE TABLE MyTable
(
ID int identity Primary key,
Name char(100),
Email char(100)
)
WITH (DATA_COMPRESSION = Page);
و برای اعمال آن به جدولی موجود از روش زیر می‌توان استفاده کرد:

Alter TABLE MyTable REBUILD WITH (DATA_COMPRESSION=Page, MAXDOP=2);
یک سری رویه‌های ذخیره شده سیستمی جدید نیز برای محاسبه حجم جداول، پیش و پس از فشرده سازی (بدون فشرده سازی واقعی) نیز در این نگارش گنجانده شده‌اند که به شرح زیر هستند:
-- بررسی اینکه چه میزان فضا با اعمال فشرده سازی صفحات قابل صرفه جویی خواهد بود
EXEC sp_estimate_data_compression_savings 'schemaname', 'TableName', NULL, NULL, 'PAGE';

-- بررسی اینکه چه میزان فضا با اعمال فشرده سازی ردیف‌ها قابل صرفه جویی خواهد بود
EXEC sp_estimate_data_compression_savings 'schemaname', 'TableName', NULL, NULL, 'ROW';

بنابراین قبل از اینکه فشرده سازی را فعال نمائید، ابتدا بررسی کنید آیا واقعا میزان قابل توجهی اطلاعات فشرده خواهند شد و نتیجه حاصل رضایت بخش است یا خیر. همچنین باید درنظر داشت که جداول و یا ایندکس‌هایی که read و write بالایی دارند برای این منظور مناسب نیستند. برای یافتن آن‌ها کوئری زیر را اجرا کنید:

USE dbName;
SELECT objectname = OBJECT_NAME(s.object_id),
indexname = i.name,
i.index_id,
reads = range_scan_count + singleton_lookup_count,
'leaf_writes' = leaf_insert_count + leaf_update_count + leaf_delete_count,
'leaf_page_splits' = leaf_allocation_count,
'nonleaf_writes' = nonleaf_insert_count + nonleaf_update_count +
nonleaf_delete_count,
'nonleaf_page_splits' = nonleaf_allocation_count
FROM sys.dm_db_index_operational_stats (DB_ID(), NULL, NULL, NULL) AS s
INNER JOIN sys.indexes AS i
ON i.object_id = s.object_id
WHERE OBJECTPROPERTY(s.object_id, 'IsUserTable') = 1
AND i.index_id = s.index_id
ORDER BY
leaf_writes DESC,
nonleaf_writes DESC

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