مسیرراهها
در بخش قبل، به چند نمونه کلی از امکانات کتابخانه Gridify اشاره کردیم. در این مقاله به معرفی کلاسها و متدهای این کتابخانه میپردازیم.
متدهای الحاقی GridifyQuery:
Filtering Operators:
GridifyQuery
از این کلاس برای اعمال تنظیمات مورد نیاز در متدهای ارائه شده توسط Gridify استفاده میشود. در ادامه به خصیصه (پراپرتی)های این کلاس میپردازیم.
- Filter : یک پراپرتی از نوع string است که درصورت مقداردهی آن، بر روی لیست خروجی ما عملیات فیلترینگ اعمال میشود. مثال :
Filter = "Name==Ali,Age>>10";
- SortBy : یک پراپرتی از نوع string است که درصورت مقداردهی آن، بر روی لیست خروجی ما عملیات چیدمان یا سورتینگ با استفاده از نام فیلد انجام میشود. مثال :
SortBy = "Age";
- IsSortAsc: یک پراپرتی از نوع bool است که مشخص کننده چیدمان به صورت نزولی و یا صعودی است.
- Page : یک پراپرتی از نوع عددی short است. از این پراپرتی برای عملیات Pagination یا صفحه بندی استفاده میشود که مشخص کننده شماره صفحه درخواستی است.
- PageSize : یک پراپرتی از نوع عددی int است که برای مشخص کردن تعداد رکورد در هر صفحه استفاده میشود.
وارد کردن این اطلاعات هنگام استفاده از کتابخانه Gridify الزامی نیست؛ به همین جهت تنها در صورت مقداردهی، از این اطلاعات استفاده میشود. درصورتیکه هیچ اطلاعاتی در این پراپرتیها وجود نداشته باشد، به صورت پیش فرض توسط Gridify نادیده گرفته میشود. البته استثنایی برای اکستنشن متد Gridify و GridifyAsync وجود دارد، به دلیل اینکه خروجی این دو متد یک کلاس <Paging<T است. در صورت اینکه مقداری برای پراپرتیهای Page و PageSize وارد نشده باشد، به صورت پیش فرض اطلاعات Page 1 با DefaultPageSize را بازمیگرداند که مقدار پیش فرض آن 10 میباشد. با استفاده از تغییر فیلد استاتیک DefaultPageSize میتوان این عدد نیز را تغییر داد.
متدهای الحاقی یا IQueryable Extensions :
برای استفاده از کتابخانه Gridify نیازی به ساخت هیچ کلاسی نیست و صرفا امکانات اینترفیس IQueryable را گسترش میدهد.
ApplyFiltering | از این متد برای اعمال فیلترینگ روی یک IQueryable استفاده میشود. این متد یک رشته متنی (string) ویا یک GridifyQuery دریافت کرده و پس از اعمال فیلترینگ یک IQueryable بازمیگرداند. |
ApplyOrdering | از این متد برای اعمال چیدمان یا Sorting روی یک IQueryable استفاده میشود. پس از اعمال چیدمان، یک IQueryable را بازمیگرداند. |
ApplyPaging | از این متد برای اعمال صفحه بندی (Pagination) استفاده میشود. پس از اعمال صفحه بندی یک IQueryable را بازمیگرداند. |
ApplyOrderingAndPaging | از این متد برای اعمال همزمان چیدمان و صفحه بندی استفاده میشود که یک IQueryable را باز میگرداند. |
ApplyFilterAndOrdering | از این متد برای اعمال همزمان فیلترینگ و چیدمان استفاده میشود که یک IQueryalbe را باز میگرداند. |
ApplyEverything | از این متد برای اعمال عملیات صفحه بندی، چیدمان و فیلترینگ استفاده میشود که یک IQueryable را باز میگرداند. |
GridifyQueryable | این متد مشابه ApplyEverything است که مقدار یک <QueryablePaging<T را برمیگرداند و دارای یک خصیصه اضافی TotalItems است که در عملیات صفحه بندی عموما نیاز داریم. (تعداد کل رکوردهای موجود در پایگاه داده، با توجه به فیلتر اعمال شده) |
Gridify | متدهای قبلی فقط به query موجود ما یکسری شرط را اضافه میکردند. ولی مسئولیت اجرای query به عهده ما بود. (مثلا با استفاده از ToList.). متد Gridify تمامی شرطها را باتوجه به GridifyQuery دریافتی اعمال کرده، سپس اطلاعات را بارگذاری کرده و یک <Paging<T را بازمیگرداند که کاملا قابل استفاده و بهینه شده برای دیتاگریدها میباشد. |
| |
GetFilteringExpression | این متد expression معادل فیلتر string نوشته شده شما را برمیگرداند که میتوانید از آن به طور مثال در متد Where در Linq استفاده نمایید. |
GetOrderingExpression | این متد expression انتخاب فیلد برای Orderby و OrderByDescending را باتوجه به مقدار وارد شده در فیلد SortBy بازمیگرداند. |
Filtering Operators:
با علائم پشتیبانی شده در Gridify برای اعمال فیلترینگ در زیر آشنا میشویم.
همانطور که در تصویر بالا مشاهده میکنید، برای اعمال فیلترینگهای پیچیده میتوانیم از چهار اپراتور , | ( ) استفاده کنیم. به همین جهت اگر نیاز داشتید که در مقدار جستجوی خود از این علائم استفاده کنید، باید قبل از هرکدام از آنها، علامت \ را اضافه کنید.
مثال رجاکس escape character در JavaScript :
let esc = (v) => v.replace(/([(),|])/g, '\\$1')
مثال #C :
var value = "(test,test2)"; var esc = Regex.Replace(value, "([(),|])", "\\$1" ); // esc = \(test\,test2\)
در بخش بعد با امکانات Mapper توکار Gridify و شخصی سازی آن آشنا خواهیم شد.
در ادامه، مراحل ارتقاء پروژههای قدیمی MVC3 را به ساختار جدید پروژههای MVC4 مرور خواهیم کرد.
1) نصب پیشنیاز
الف) نصب VS 2012
و یا
ب) نصب بسته MVC4 مخصوص VS 2010 (این مورد جهت سرورهای وب نیز توصیه میشود)
پس از نصب باید به این نکته دقت داشت که پوشههای زیر حاوی اسمبلیهای جدید MVC4 هستند و نیازی نیست الزاما این موارد را از NuGet دریافت و نصب کرد:
پس از نصب پیشنیازها
2) نیاز است نوع پروژه ارتقاء یابد
به پوشه پروژه MVC3 خود مراجعه کرده و تمام فایلهای csproj و web.config موجود را با یک ادیتور متنی باز کنید (از خود ویژوال استودیو استفاده نکنید، زیرا نیاز است محتوای فایلهای پروژه نیز دستی ویرایش شوند).
در فایلهای csproj (یا همان فایل پروژه؛ که vbproj هم میتواند باشد) عبارت
را جستجو کرده و با
جایگزین کنید. به این ترتیب نوع پروژه به MVC4 تبدیل میشود.
3) به روز رسانی شماره نگارشهای قدیمی
سپس تعاریف اسمبلیهای قدیمی نگارش سه MVC و نگارش یک Razor را یافته (در تمام فایلها، چه فایلهای پروژه و چه تنظیمات):
و اینها را با نگارش چهار MVC و نگارش دو Razor جایگزین کنید:
این کارها را با replace in all open documents توسط notepad plus-plus به سادگی میتوان انجام داد.
4) به روز رسانی مسیرهای قدیمی
به علاوه اگر در پروژههای خود از اسمبلیهای قدیمی به صورت مستقیم استفاده شده:
اینها را یافته و به نگارش MVC4 و Razor2 تغییر دهید:
5) به روز رسانی قسمت appSettings فایلهای کانفیگ
در کلیه فایلهای web.config برنامه، webpages:Version را یافته و شماره نگارش آنرا از یک به دو تغییر دهید:
همچنین یک سطر جدید PreserveLoginUrl را نیز مطابق تنظیم فوق اضافه نمائید.
6) رسیدگی به وضعیت اسمبلیهای شرکتهای ثالث
ممکن است در این زمان از تعدادی کامپوننت و اسمبلی MVC3 تهیه شده توسط شرکتهای ثالث نیز استفاده نمائید. برای اینکه این اسمبلیها را وادار نمائید تا از نگارشهای MVC4 و Razor2 استفاده کنند، نیاز است bindingRedirectهای زیر را به فایلهای web.config برنامه اضافه کنید (در فایل کانفیگ ریشه پروژه):
اکنون فایل solution را در VS.NET گشوده و یکبار گزینه rebuild را انتخاب کنید تا پروژه مجددا بر اساس اسمبلیهای جدید معرفی شده ساخته شود.
7) استفاده از NuGet برای به روز رسانی بستههای نصب شده
یک سری از بستههای تشکیل دهنده MVC3 مانند موارد ذیل نیز به روز شدهاند که لازم است از طریق NuGet دریافت و جایگزین شوند:
Unobtrusive.Ajax.2
Unobtrusive.Validation.2
Web.Optimization.1.0.0
و ....
برای اینکار در solution explorer روی references کلیک راست کرده و گزینه Manage NuGet Packages را انتخاب کنید. در صفحه باز شده گزینه updates/all را انتخاب کرده و مواردی را که لیست میکند به روز نمائید (شامل جی کوئری، EF، structureMap و غیره خواهد بود).
8) اضافه کردن یک فضای نام جدید
بسته Web Optimization را از طریق NuGet دریافت کنید (برای یافتن آن bundling را جستجو کنید؛ نام کامل آن Microsoft ASP.NET Web Optimization Framework 1.0.0 است). این مورد به همراه پوشه MVC4 نیست و باید از طریق NuGet دریافت و نصب شود. (البته پروژههای جدید MVC4 شامل این مورد هستند)
در فایل وب کانفیگ، فضای نام System.Web.Optimization را نیز اضافه نمائید:
پس از ارتقاء
اولین مشکلی که مشاهده شد:
بعد از rebuild به مقدار پارامتر salt که به نحو زیر در MVC3 تعریف شده بود، ایراد خواهد گرفت:
Salt را در MVC4 منسوخ شده معرفی کردهاند: (^)
علت هم این است که salt را اینبار به نحو صحیحی خودشان در پشت صحنه تولید و اعمال میکنند. بنابراین این یک مورد را کلا از کدهای خود حذف کنید که نیازی نیست.
مشکل بعدی:
در EF 5 جای یک سری از کلاسها تغییر کرده. مثلا ویژگیهای ForeignKey، ComplexType و ... به فضای نام System.ComponentModel.DataAnnotations.Schema منتقل شدهاند. در همین حد تغییر جهت کامپایل مجدد کدها کفایت میکند.
همچنین فایلهای پروژه موجود را باز کرده و EntityFramework, Version=4.1.0.0 را جستجو کنید. نگارش جدید 4.4.0.0 است که باید اصلاح شود (این موارد را بهتر است توسط یک ادیتور معمولی خارج از VS.NET ویرایش کنید).
در زمان نگارش این مطلب EF Mini Profiler با EF 5 سازگار نیست. بنابراین اگر از آن استفاده میکنید نیاز است غیرفعالش کنید.
اولین استفاده از امکانات جدید MVC4:
استفاده از امکانات System.Web.Optimization که ذکر گردید، میتواند اولین تغییر مفید محسوب شود.
برای اینکه با نحوه کار آن بهتر آشنا شوید، یک پروژه جدید MVC4 را در VS.NET (از نوع basic) آغاز کنید. به صورت خودکار یک پوشه جدید را به نام App_Start به ریشه پروژه اضافه میکند. داخل آن فایل مثال BundleConfig قرار دارد. این کلاس در فایل global.asax برنامه نیز ثبت شدهاست. باید دقت داشت در حالت دیباگ (compilation debug=true در وب کانفیگ) تغییر خاصی را ملاحظه نخواهید کرد.
تمام اینها خوب؛ اما من به نحو زیر از این امکان جدید استفاده میکنم:
کلاس BundleConfig فوق را به مجموعه کلاسهای کمکی خود اضافه کنید.
چند نکته مهم در این کلاس وجود دارد:
الف) توسط AsIsBundleOrderer فایلها به همان ترتیبی که به سیستم اضافه میشوند، در حاصل نهایی ظاهر خواهند شد. حالت پیش فرض مرتب سازی، بر اساس حروف الفباء است و ... خصوصا برای اسکریپتهایی که ترتیب معرفی آنها مهم است، مساله ساز خواهد بود.
ب)BundleTable.EnableOptimizations سبب میشود تا حتی در حالت debug نیز فشرده سازی را مشاهده کنید.
ج) متدهای کمکی تعریف شده این امکان را میدهند تا بدون نیاز به کامپایل مجدد پروژه، به سادگی در کدهای Razor بتوانید اسکریپتها را اضافه کنید.
سپس نحوه جایگزینی تعاریف قبلی موجود در فایلهای Razor با سیستم جدید، به نحو زیر است:
پارامتر اول این متدها، سبب تعریف خودکار routing میشود. برای مثال اولین تعریف، آدرس خودکار زیر را تولید میکند:
بنابراین تعریف دقیق آن مهم است. خصوصا اگر فایلهای شما در پوشهها و زیرپوشههای متعددی قرار گرفته نمیتوان تمام آنها را در طی یک مرحله معرفی نمود. هر سطح را باید از طریق یک بار معرفی به سیستم اضافه کرد. مثلا اگر یک زیر پوشه به نام noty دارید (Content/noty)، چون در یک سطح و زیرپوشه مجزا قرار دارد، باید نحوه تعریف آن به صورت زیر باشد:
این مورد خصوصا در مسیریابی تصاویر مرتبط با اسکریپتها و شیوه نامهها مؤثر است؛ وگرنه این تصاویر تعریف شده در فایلهای CSS یافت نخواهند شد (تمام مثالهای موجود در وب با این مساله مشکل دارند و فرض آنها بر این است که کلیه فایلهای خود را در یک پوشه، بدون هیچگونه زیرپوشهای تعریف کردهاید).
پارامترهای بعدی، محل قرارگیری اسکریپتها و CSSهای برنامه هستند و همانطور که عنوان شد اینبار با خیال راحت میتوانید ترتیب معرفی خاصی را مدنظر داشته باشید؛ زیرا توسط AsIsBundleOrderer به صورت پیش فرض لحاظ خواهد شد.
1) نصب پیشنیاز
الف) نصب VS 2012
و یا
ب) نصب بسته MVC4 مخصوص VS 2010 (این مورد جهت سرورهای وب نیز توصیه میشود)
پس از نصب باید به این نکته دقت داشت که پوشههای زیر حاوی اسمبلیهای جدید MVC4 هستند و نیازی نیست الزاما این موارد را از NuGet دریافت و نصب کرد:
C:\Program Files\Microsoft ASP.NET\ASP.NET Web Pages\v2.0\Assemblies C:\Program Files\Microsoft ASP.NET\ASP.NET MVC 4\Assemblies
2) نیاز است نوع پروژه ارتقاء یابد
به پوشه پروژه MVC3 خود مراجعه کرده و تمام فایلهای csproj و web.config موجود را با یک ادیتور متنی باز کنید (از خود ویژوال استودیو استفاده نکنید، زیرا نیاز است محتوای فایلهای پروژه نیز دستی ویرایش شوند).
در فایلهای csproj (یا همان فایل پروژه؛ که vbproj هم میتواند باشد) عبارت
{E53F8FEA-EAE0-44A6-8774-FFD645390401}
{E3E379DF-F4C6-4180-9B81-6769533ABE47}
3) به روز رسانی شماره نگارشهای قدیمی
سپس تعاریف اسمبلیهای قدیمی نگارش سه MVC و نگارش یک Razor را یافته (در تمام فایلها، چه فایلهای پروژه و چه تنظیمات):
System.Web.Mvc, Version=3.0.0.0 System.Web.WebPages, Version=1.0.0.0 System.Web.Helpers, Version=1.0.0.0 System.Web.WebPages.Razor, Version=1.0.0.0
System.Web.Mvc, Version=4.0.0.0 System.Web.WebPages, Version=2.0.0.0 System.Web.Helpers, Version=2.0.0.0 System.Web.WebPages.Razor, Version=2.0.0.0
4) به روز رسانی مسیرهای قدیمی
به علاوه اگر در پروژههای خود از اسمبلیهای قدیمی به صورت مستقیم استفاده شده:
C:\Program Files\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\Assemblies C:\Program Files\Microsoft ASP.NET\ASP.NET MVC 3\Assemblies
C:\Program Files\Microsoft ASP.NET\ASP.NET Web Pages\v2.0\Assemblies C:\Program Files\Microsoft ASP.NET\ASP.NET MVC 4\Assemblies
5) به روز رسانی قسمت appSettings فایلهای کانفیگ
در کلیه فایلهای web.config برنامه، webpages:Version را یافته و شماره نگارش آنرا از یک به دو تغییر دهید:
<appSettings> <add key="webpages:Version" value="2.0.0.0" /> <add key="PreserveLoginUrl" value="true" /> </appSettings>
6) رسیدگی به وضعیت اسمبلیهای شرکتهای ثالث
ممکن است در این زمان از تعدادی کامپوننت و اسمبلی MVC3 تهیه شده توسط شرکتهای ثالث نیز استفاده نمائید. برای اینکه این اسمبلیها را وادار نمائید تا از نگارشهای MVC4 و Razor2 استفاده کنند، نیاز است bindingRedirectهای زیر را به فایلهای web.config برنامه اضافه کنید (در فایل کانفیگ ریشه پروژه):
<configuration> <!--... elements deleted for clarity ...--> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="4.0.0.0"/> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/> </dependentAssembly> </assemblyBinding> </runtime> </configuration>
7) استفاده از NuGet برای به روز رسانی بستههای نصب شده
یک سری از بستههای تشکیل دهنده MVC3 مانند موارد ذیل نیز به روز شدهاند که لازم است از طریق NuGet دریافت و جایگزین شوند:
Unobtrusive.Ajax.2
Unobtrusive.Validation.2
Web.Optimization.1.0.0
و ....
برای اینکار در solution explorer روی references کلیک راست کرده و گزینه Manage NuGet Packages را انتخاب کنید. در صفحه باز شده گزینه updates/all را انتخاب کرده و مواردی را که لیست میکند به روز نمائید (شامل جی کوئری، EF، structureMap و غیره خواهد بود).
8) اضافه کردن یک فضای نام جدید
بسته Web Optimization را از طریق NuGet دریافت کنید (برای یافتن آن bundling را جستجو کنید؛ نام کامل آن Microsoft ASP.NET Web Optimization Framework 1.0.0 است). این مورد به همراه پوشه MVC4 نیست و باید از طریق NuGet دریافت و نصب شود. (البته پروژههای جدید MVC4 شامل این مورد هستند)
در فایل وب کانفیگ، فضای نام System.Web.Optimization را نیز اضافه نمائید:
<pages> <namespaces> <add namespace="System.Web.Optimization" /> </namespaces> </pages>
پس از ارتقاء
اولین مشکلی که مشاهده شد:
بعد از rebuild به مقدار پارامتر salt که به نحو زیر در MVC3 تعریف شده بود، ایراد خواهد گرفت:
[ValidateAntiForgeryToken(Salt = "data123")]
علت هم این است که salt را اینبار به نحو صحیحی خودشان در پشت صحنه تولید و اعمال میکنند. بنابراین این یک مورد را کلا از کدهای خود حذف کنید که نیازی نیست.
مشکل بعدی:
در EF 5 جای یک سری از کلاسها تغییر کرده. مثلا ویژگیهای ForeignKey، ComplexType و ... به فضای نام System.ComponentModel.DataAnnotations.Schema منتقل شدهاند. در همین حد تغییر جهت کامپایل مجدد کدها کفایت میکند.
همچنین فایلهای پروژه موجود را باز کرده و EntityFramework, Version=4.1.0.0 را جستجو کنید. نگارش جدید 4.4.0.0 است که باید اصلاح شود (این موارد را بهتر است توسط یک ادیتور معمولی خارج از VS.NET ویرایش کنید).
در زمان نگارش این مطلب EF Mini Profiler با EF 5 سازگار نیست. بنابراین اگر از آن استفاده میکنید نیاز است غیرفعالش کنید.
اولین استفاده از امکانات جدید MVC4:
استفاده از امکانات System.Web.Optimization که ذکر گردید، میتواند اولین تغییر مفید محسوب شود.
برای اینکه با نحوه کار آن بهتر آشنا شوید، یک پروژه جدید MVC4 را در VS.NET (از نوع basic) آغاز کنید. به صورت خودکار یک پوشه جدید را به نام App_Start به ریشه پروژه اضافه میکند. داخل آن فایل مثال BundleConfig قرار دارد. این کلاس در فایل global.asax برنامه نیز ثبت شدهاست. باید دقت داشت در حالت دیباگ (compilation debug=true در وب کانفیگ) تغییر خاصی را ملاحظه نخواهید کرد.
تمام اینها خوب؛ اما من به نحو زیر از این امکان جدید استفاده میکنم:
using System.Collections.Generic; using System.IO; using System.Web; using System.Web.Optimization; namespace Common.WebToolkit { /// <summary> /// A custom bundle orderer (IBundleOrderer) that will ensure bundles are /// included in the order you register them. /// </summary> public class AsIsBundleOrderer : IBundleOrderer { public IEnumerable<FileInfo> OrderFiles(BundleContext context, IEnumerable<FileInfo> files) { return files; } } public static class BundleConfig { private static void addBundle(string virtualPath, bool isCss, params string[] files) { BundleTable.EnableOptimizations = true; var existing = BundleTable.Bundles.GetBundleFor(virtualPath); if (existing != null) return; var newBundle = isCss ? new Bundle(virtualPath, new CssMinify()) : new Bundle(virtualPath, new JsMinify()); newBundle.Orderer = new AsIsBundleOrderer(); foreach (var file in files) newBundle.Include(file); BundleTable.Bundles.Add(newBundle); } public static IHtmlString AddScripts(string virtualPath, params string[] files) { addBundle(virtualPath, false, files); return Scripts.Render(virtualPath); } public static IHtmlString AddStyles(string virtualPath, params string[] files) { addBundle(virtualPath, true, files); return Styles.Render(virtualPath); } public static IHtmlString AddScriptUrl(string virtualPath, params string[] files) { addBundle(virtualPath, false, files); return Scripts.Url(virtualPath); } public static IHtmlString AddStyleUrl(string virtualPath, params string[] files) { addBundle(virtualPath, true, files); return Styles.Url(virtualPath); } } }
چند نکته مهم در این کلاس وجود دارد:
الف) توسط AsIsBundleOrderer فایلها به همان ترتیبی که به سیستم اضافه میشوند، در حاصل نهایی ظاهر خواهند شد. حالت پیش فرض مرتب سازی، بر اساس حروف الفباء است و ... خصوصا برای اسکریپتهایی که ترتیب معرفی آنها مهم است، مساله ساز خواهد بود.
ب)BundleTable.EnableOptimizations سبب میشود تا حتی در حالت debug نیز فشرده سازی را مشاهده کنید.
ج) متدهای کمکی تعریف شده این امکان را میدهند تا بدون نیاز به کامپایل مجدد پروژه، به سادگی در کدهای Razor بتوانید اسکریپتها را اضافه کنید.
سپس نحوه جایگزینی تعاریف قبلی موجود در فایلهای Razor با سیستم جدید، به نحو زیر است:
@using Common.WebToolkit <link href="@BundleConfig.AddStyleUrl("~/Content/blueprint/print", "~/Content/blueprint/print.css")" rel="stylesheet" type="text/css" media="print"/> @BundleConfig.AddScripts("~/Scripts/js", "~/Scripts/jquery-1.8.0.min.js", "~/Scripts/jquery.unobtrusive-ajax.min.js", "~/Scripts/jquery.validate.min.js") @BundleConfig.AddStyles("~/Content/css", "~/Content/Site.css", "~/Content/buttons.css")
http://site/Content/blueprint/print?v=hash
@BundleConfig.AddStyles("~/Content/noty/css", "~/Content/noty/jquery.noty.css", "~/Content/noty/noty_theme_default.css")
پارامترهای بعدی، محل قرارگیری اسکریپتها و CSSهای برنامه هستند و همانطور که عنوان شد اینبار با خیال راحت میتوانید ترتیب معرفی خاصی را مدنظر داشته باشید؛ زیرا توسط AsIsBundleOrderer به صورت پیش فرض لحاظ خواهد شد.
اشتراکها
سری «سلامت کد» از گوگل
اشتراکها
SignalR 2.1.0 منتشر شد
مطالب دورهها
نگاهی به افزونههای کار با اسناد در RavenDB
توانمندیهای RavenDB جهت کار با اسناد، صرفا به ذخیره و ویرایش آنها محدود نمیشوند. در ادامه، مباحثی مانند پیوست فایلهای باینری به اسناد، نگهداری نگارشهای مختلف آنها، حذف آبشاری اسناد و وصله کردن آنها را مورد بررسی قرار خواهیم داد. تعدادی از این قابلیتها توکار هستند و تعدادی دیگر توسط افزونههای آن فراهم شدهاند.
پیوست و بازیابی فایلهای باینری
امکان پیوست فایلهای باینری نیز به اسناد RavenDB وجود دارد. برای مثال به کلاس سؤالات قسمت اول این سری، خاصیت FileId را اضافه کنید:
اکنون برای ذخیره فایلی و همچنین انتساب آن به یک سند، به روش ذیل باید عمل کرد:
کار متد store.DatabaseCommands.PutAttachment، ارسال اطلاعات یک استریم به سرور RavenDB است که تحت کلید مشخصی ذخیره خواهد شد. متد استاندارد System.IO.File.OpenRead روش مناسبی است برای دریافت استریمها و ارسال آن به متد PutAttachment. در قسمت metadata این فایل، توسط شیء RavenJObject، یک دیکشنری از key-valueها را جهت درج اطلاعات اضافی مرتبط با هر فایل میتوان مقدار دهی کرد. پس از آن، جهت انتساب این فایل ارسال شده به یک سند، تنها کافی است کلید آنرا به خاصیت FileId انتساب دهیم.
در این حالت اگر به خروجی دیباگ سرور نیز دقت کنیم، مسیر ذخیره سازی این نوع فایلها مشخص میشود:
بازیابی فایلهای همراه با اسناد نیز بسیار ساده است:
فقط کافی است سند را یکبار Load کرده و سپس از متد store.DatabaseCommands.GetAttachment برای دستیابی به فایل پیوست شده استفاده نمائیم.
وصله کردن اسناد
سند سؤالات قسمت اول و پاسخهای آن، همگی داخل یک سند هستند. اکنون برای اضافه کردن یک آیتم به این لیست، یک راه، واکشی کل آن سند است و سپس افزودن یک آیتم جدید به لیست پاسخها و یا در این حالت، جهت کاهش ترافیک سرور و سریعتر شدن کار، RavenDB مفهوم Patching یا وصله کردن اسناد را ارائه داده است. در این روش بدون واکشی کل سند، میتوان قسمتی از سند را وصله کرد و تغییر داد.
برای وصله کردن اسناد از متد store.DatabaseCommands.Patch استفاده میشود. در اینجا ابتدا Id سند مورد نظر مشخص شده و سپس آرایهای از تغییرات لازم را به صورت اشیاء PatchRequest ارائه میدهیم. در هر PatchRequest، خاصیت Type مشخص میکند که حین عملیات وصله کردن چه کاری باید صورت گیرد؛ برای مثال اطلاعات ارسالی اضافه شوند یا ویرایش و امثال آن. خاصیت Name، نام خاصیت در حال تغییر را مشخص میکند. برای مثال در اینجا میخواهیم به مجموعه پاسخهای یک سند، آیتم جدیدی را اضافه کنیم. خاصیت Value، مقدار جدید را دریافت خواهد کرد. این مقدار باید با فرمت JSON تنظیم شود؛ به همین جهت از متد توکار RavenJObject.FromObject برای اینکار استفاده شده است.
افزونههای RavenDB
قابلیتهای ذکر شده فوق جهت کار با اسناد به صورت توکار در RavenDB مهیا هستند. این سیستم افزونه پذیر است و تاکنون افزونههای متعددی برای آن تهیه شدهاند که در اینجا به آنها Bundles گفته میشوند. برای استفاده از آنها تنها کافی است فایل DLL مرتبط را درون پوشه Plugins سرور، کپی کنیم. دریافت آنها نیز از طریق NuGet پشتیبانی میشود؛ و یا سورس آنها را دریافت کرده و کامپایل کنید. در ادامه تعدادی از این افزونهها را بررسی خواهیم کرد.
حذف آبشاری اسناد
فایل افزونه حذف آبشاری اسناد را از طریق دستور نیوگت فوق میتوان دریافت کرد. سپس فایل Raven.Bundles.CascadeDelete.dl دریافتی را درون پوشه plugins کنار فایل exe سرور RavenDB کپی کنید تا قابل استفاده شود.
استفاده مهم این افزونه، حذف پیوستهای باینری اسناد و یا حذف اسناد مرتبط با یک سند، پس از حذف سند اصلی است (که به صورت پیش فرض انجام نمیشود).
یک مثال:
برای استفاده از آن باید از متد session.Advanced.GetMetadataFor استفاده کرد. در اینجا شیء post که دارای تعدادی کامنت است، مشخص میشود. سپس با مشخص سازی Raven-Cascade-Delete-Documents و ذکر Id کامنتهای مرتبطی که باید حذف شوند، تمام این اسناد با هم پس از حذف post، حذف خواهند شد. همچنین دستور Raven-Cascade-Delete-Attachments سبب حذف فایلهای مشخص شده با Id مرتبط با یک سند، میگردد.
نگهداری و بازیابی نگارشهای مختلف اسناد
فایل افزونه Versioning اسناد را از طریق دستور نیوگت فوق میتوان دریافت کرد. سپس فایل dll دریافتی را درون پوشه plugins کنار فایل exe سرور RavenDB کپی کنید تا قابل استفاده شود. فایل Raven.Bundles.Versioning.dll باید در پوشه افزونهها کپی شود و فایل Raven.Client.Versioning.dll به برنامه ما ارجاع داده خواهد شد.
با استفاده از قابلیت document versioning میتوان تغییرات اسناد را در طول زمان، ردیابی کرد؛ همچنین حذف یک سند، این سابقه را از بین نخواهد برد.
تنظیمات اولیه آن به این صورت است که توسط شیء VersioningConfiguration به سشن جاری اعلام میکنیم که چند نگارش از اسناد را ذخیره کند. اگر Exclude آن به true تنظیم شود، اینکار صورت نخواهد گرفت.
تنظیم Id به Raven/Versioning/DefaultConfiguration، سبب خواهد شد تا VersioningConfiguration فوق به تمام اسناد اعمال شود. اگر نیاز است برای مثال تنها به BlogPosts اعمال شود، این Id را باید به Raven/Versioning/BlogPosts تنظیم کرد.
بازیابی نگارشهای مختلف یک سند، صرفا از طریق متد Load میسر است و در اینجا شماره Id نگارش به انتهای Id سند اضافه میشود. برای مثال "blogposts/1/revisions/1" به نگارش یک مطلب شماره یک اشاره میکند.
برای بدست آوردن سه نگارش آخر یک سند باید از متد ذیل استفاده کرد:
پیوست و بازیابی فایلهای باینری
امکان پیوست فایلهای باینری نیز به اسناد RavenDB وجود دارد. برای مثال به کلاس سؤالات قسمت اول این سری، خاصیت FileId را اضافه کنید:
public class Question { public string FileId { set; get; } }
using (var store = new DocumentStore { Url = "http://localhost:8080" }.Initialize()) { using (var session = store.OpenSession()) { store.DatabaseCommands.PutAttachment(key: "file/1", etag: null, data: System.IO.File.OpenRead(@"D:\Prog\packages.config"), metadata: new RavenJObject { { "Description", "توضیحات فایل" } }); var question = new Question { By = "users/Vahid", Title = "Raven Intro", Content = "Test....", FileId = "file/1" }; session.Store(question); session.SaveChanges(); } }
در این حالت اگر به خروجی دیباگ سرور نیز دقت کنیم، مسیر ذخیره سازی این نوع فایلها مشخص میشود:
Request # 2: PUT - 200 ms - <system> - 201 - /static/file/1
using (var store = new DocumentStore { Url = "http://localhost:8080" }.Initialize()) { using (var session = store.OpenSession()) { var question = session.Load<Question>("questions/97"); var file1 = store.DatabaseCommands.GetAttachment(question.FileId); Console.WriteLine(file1.Size); } }
وصله کردن اسناد
سند سؤالات قسمت اول و پاسخهای آن، همگی داخل یک سند هستند. اکنون برای اضافه کردن یک آیتم به این لیست، یک راه، واکشی کل آن سند است و سپس افزودن یک آیتم جدید به لیست پاسخها و یا در این حالت، جهت کاهش ترافیک سرور و سریعتر شدن کار، RavenDB مفهوم Patching یا وصله کردن اسناد را ارائه داده است. در این روش بدون واکشی کل سند، میتوان قسمتی از سند را وصله کرد و تغییر داد.
using (var store = new DocumentStore { Url = "http://localhost:8080" }.Initialize()) { using (var session = store.OpenSession()) { store.DatabaseCommands.Patch(key: "questions/97", patches: new[] { new PatchRequest { Type = PatchCommandType.Add, Name = "Answers", Value = RavenJObject.FromObject(new Answer{ By= "users/Vahid", Content="data..."}) } }); } }
افزونههای RavenDB
قابلیتهای ذکر شده فوق جهت کار با اسناد به صورت توکار در RavenDB مهیا هستند. این سیستم افزونه پذیر است و تاکنون افزونههای متعددی برای آن تهیه شدهاند که در اینجا به آنها Bundles گفته میشوند. برای استفاده از آنها تنها کافی است فایل DLL مرتبط را درون پوشه Plugins سرور، کپی کنیم. دریافت آنها نیز از طریق NuGet پشتیبانی میشود؛ و یا سورس آنها را دریافت کرده و کامپایل کنید. در ادامه تعدادی از این افزونهها را بررسی خواهیم کرد.
حذف آبشاری اسناد
PM> Install-Package RavenDB.Bundles.CascadeDelete -Pre
استفاده مهم این افزونه، حذف پیوستهای باینری اسناد و یا حذف اسناد مرتبط با یک سند، پس از حذف سند اصلی است (که به صورت پیش فرض انجام نمیشود).
یک مثال:
var comment = new Comment { PostId = post.Id }; session.Store(comment); session.Advanced.GetMetadataFor(post)["Raven-Cascade-Delete-Documents"] = RavenJToken.FromObject(new[] { comment.Id }); session.Advanced.GetMetadataFor(post)["Raven-Cascade-Delete-Attachments"] = RavenJToken.FromObject(new[] { "picture/1" }); session.SaveChanges();
نگهداری و بازیابی نگارشهای مختلف اسناد
PM> Install-Package RavenDB.Bundles.Versioning
با استفاده از قابلیت document versioning میتوان تغییرات اسناد را در طول زمان، ردیابی کرد؛ همچنین حذف یک سند، این سابقه را از بین نخواهد برد.
تنظیمات اولیه آن به این صورت است که توسط شیء VersioningConfiguration به سشن جاری اعلام میکنیم که چند نگارش از اسناد را ذخیره کند. اگر Exclude آن به true تنظیم شود، اینکار صورت نخواهد گرفت.
session.Store(new VersioningConfiguration { Exclude = false, Id = "Raven/Versioning/DefaultConfiguration", MaxRevisions = 5 });
بازیابی نگارشهای مختلف یک سند، صرفا از طریق متد Load میسر است و در اینجا شماره Id نگارش به انتهای Id سند اضافه میشود. برای مثال "blogposts/1/revisions/1" به نگارش یک مطلب شماره یک اشاره میکند.
برای بدست آوردن سه نگارش آخر یک سند باید از متد ذیل استفاده کرد:
var lastThreeVersions = session.Advanced.GetRevisionsFor<BlogPost>(post.Id, 0, 3);