نظرات مطالب
تفاوت AngularJS با KnockoutJS
در واقع زمانی که تنها از ماژول Data binding استفاده می‌شود یعنی به عنوان مثال تنها از موتور بنز استفاده شده . 
بازخوردهای دوره
ایجاد یک کلاس جدید پویا و وهله‌ای از آن در زمان اجرا توسط Reflection.Emit
با سلام، من می‌خواهم در یکی از پروژه‌ها از این روش استفاده کنم و سناریویی که من روی اون کار می‌کنم به صورت زیر است:

درون دیتابیس، یک Table دارم که درون این Table نام تمام موجودیت‌های سیستم خودم رو نگه می‌دارم و در یک Table دیگر تمام فیلدهای موجودیت‌ها را همراه با نوع داده آنها ذخیره می‌کنم

برای یک سری شرایط خاص می‌خواهم کار زیر را انجام دهم:

یک فرم طراحی کردم که برای تمام موجودیت‌های تعریف شده درون جدول Entities کاربرد داره ، می‌خواهم زمانی که این فرم اجرا شده با توجه به اینکه این فرم برای کدام موجودیت فراخوانی شده است یک کلاس برای آن موجودیت ایجاد کنم و پس از آن یک لیست از کلاسی که ایجاد شده ، ایجاد بکنم و درون آن لیست مقادیری را قرار دهم (مقادیر را از دیتابیس خوانده می‌شود) و در آخر مقادیر لیست را در یک کنترل مثل gridview نمایش دهم

حال من برای انجام این کار به چند مشکل برخوردم . کدی که نوشتم به صورت زیر است
 var ctx = new Entities();
            var Fields = ctx.ENTITIES_FEILDS.ToList();
            var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
                                    name: new AssemblyName("Demo"), access: AssemblyBuilderAccess.Run);

            var moduleBuilder = assemblyBuilder.DefineDynamicModule(name: "Module");

            var typeBuilder = moduleBuilder.DefineType(name: Fields.First(c=>c.FEILD_ID==1).ENTITIES.ENTITY_NAME, attr: TypeAttributes.Public);

            foreach (var item in Fields)
            {
                   
            }
در اینجا یک کلاس همنام با نام موجودیت ایجاد کردم و تمام فیلدهای این موجودیت را واکشی کردم حال می‌خواهم به ازای هر فیلد، یک Property ایجاد کنم. با توجه به مطلبی که در بالا فرموید اگر ما تعداد فیلدهامون از قبل مشخص بود به راحتی می‌توانستیم این کار رو انجام بدیم ولی الان که مشخص نیست چگونه می‌توانیم Property  خودمان را اضافه کنم؟
مطالب
قسمت سوم : بررسی تعدادی از ویژگی های Telerik Reporting
در این بخش قصد داریم به طور خلاصه تعدادی از ویژگی‌های Telerik Reporting را جهت ساخت گزارشات مورد بررسی قرار دهیم.
ویژگی‌های مورد بحث شامل موارد زیر می‌باشند:
•  ویرایش TextBox‌ها در محیط Designer
•  Copy و Paste کردن Style‌ها از یک کنترل به کنترل دیگر
•  قالب بندی شرطی
•  پیمایش و تغییر اندازه گزارش و آیتم‌های آن
•  تغییر اندازه بخش‌های مختلف گزارش نظیر Page Header ، Detail و ...
•  افزودن TextBox Shape و PictureBox درون Designer گزارش
•  استفاده از پنجره Data Explorer
•  استفاده از پنجره Report Explorer
در ادامه به بررسی موارد ذکر شده جهت طراحی گزارش می‌پردازیم.
1.  جهت تغییر محتوای یک TextBox می‌توان روی آن دوبار کلیک نمود. پس از آن TextBox به حالت ویرایش می‌رود و می‌توان متن درون آن را به سادگی تغییر داد.این کار در محیط Designer انجام می‌شود و نیازی نیست برای تغییر محتوای TextBox به پنجره Properties بروید و متن آن را تغییر دهید.
2.  در محیط Designer به راحتی می‌توانید گزارش خود را Zoom نمایید.این کار توسط ComboBox مربوطه در پایین سمت چپ Designer انجام می‌شود.

3. اگر قرار باشد TextBox جدیدی به گزارش خود اضافه نمایید، کافی است آن را از بخش ToolBox به محیط گزارش بکشید و سپس به چینش آن بپردازید. 

4. در محیط طراح گزارش Telerik می‌توانید به راحتی یک قالب بندی و یا Style را از کنترلی به کنترل دیگر کپی نمایید و در وقت خود جهت طراحی گزارش صرفه جویی نمایید. برای انجام اینکار کافی است روی کنترلی که قرار است Style آن را کپی نمایید راست کلیک نموده و پس از آن از منوی ظاهر شده گزینه Copy Style را انتخاب نمایید. در ادامه می‌توانید کنترل و یا کنترل هایی که قرار است قالب بندی را به آنها اعمال کنید انتخاب نموده ، روی آنها راست کلیک نمایید و گزینه Paste Style را انتخاب کنید.با این کار Style ی که در مرحله قبل از کنترلی دیگر کپی کرده بودید به کنترل یا کنترل‌های انتخاب شده اعمال می‌شود.  

5. یکی دیگر از امکانات Telerik Reporting امکان قالب بندی شرطی (Conditional Formating) می‌باشد. یعنی Style یک کنترل توسط شرط‌ها تعیین می‌شود. برای مثال می‌توانیم بگوییم که اگر مقدار فروش بیشتر از مبلغ خاصی بود ، عدد نمایش داده شده با رنگ سبز نمایش داده شود و یا اینکه از فونت و یا اندازه دیگری جهت نمایش آن استفاده شود (به طور کلی با توجه به شرط‌های تعیین شده  نمایش آن کنترل با یک Style متفاوت صورت گیرد). در قسمت‌های آینده به بررسی کامل این قابلیت نیز خواهیم پرداخت.  

6. یکی از امکاناتی که در هنگام طراحی گزارش در اختیار ما قرار میگیرد پنجره Data Explorer می‌باشد. توسط این پنجره می‌توان فیلدهای یک منبع داده (DataSource) را مشاهده نمود و برای اینکه بتوان از آنها در محیط طراحی استفاده کرد بر روی محیط طراحی درگ نمود. DataSource‌ها انواع مختلفی دارند که در قسمت اول این آموزش به معرفی آنها پرداختیم و از نمونه Sql آن نیز جهت طراحی یک گزارش ساده استفاده کردیم. در ادامه نیز با این موارد بیشتر آشنا خواهید شد.در تصویر زیر نحوه‌ی درگ کردن یک فیلد تصویر را از پنجره Data Explorer مشاهده می‌نمایید.  

7. یکی دیگر از اجزای Reporting پنجره‌ی Report Explorer می‌باشد. توسط این پنجره می‌توان دسترسی سریعی به اجزای درون گزارش داشت. برای مثال می‌توان به راحتی یک بخش درون گزارش را انتخاب نمود و در پنجره‌ی Properties تغییراتی در آن اعمال نمود.  


ادامه دارد ...

مطالب
آشنایی با Promises در جاوا اسکریپت
در حین انجام اعمال غیرهمزمان جاوا اسکریپتی مانند فراخوانی‌های jQuery AJAX، برای مدیریت دریافت نتایج، عموما از یک سری callback استفاده می‌شود. برای مثال:
 $.get('http://site-url', function(data) {
//این تابع پس از پایان کار عملیات ای‌جکسی در آینده فراخوانی خواهد شد
});
تا اینجا مشکلی به نظر نمی‌رسد. اما مورد ذیل چطور؟
$.get('http://site-url/0', function(data0) {
    // callback #1
    $.get('http://site-url/1', function(data1) {
        // callback #2
        $.post('http://site-url/2', function(data2) {
            // callback #3
        });
    });
});
در اینجا نیاز است پس از پایان کار عملیات Ajax ایی اول، عملیات دوم و پس از آن عملیات سومی انجام شود. همانطور که مشاهده می‌کنید، این نوع کدها به سرعت از کنترل خارج می‌شوند؛ خوانایی پایینی داشته و مدیریت استثناءهای رخ داده در آن‌ها نیز در این بین مشکل است. از این جهت که خطاهای هر کدام به سطحی بالاتر منتقل نمی‌شود و باید همانجا محلی و داخل هر callback مدیریت گردد.
روش‌های زیادی برای حل این مساله ارائه شده‌است و در حال حاضر کار کردن با promiseها متداول‌ترین روش حل مدیریت فراخوانی کدهای همزمان جاوا اسکریپتی است. برای نمونه اگر از AngularJS استفاده کنید، سرویس‌های آن برای دریافت اطلاعات از سرور، از یک چنین مفهومی استفاده می‌کنند.


Promise در جاوا اسکریپت چیست؟

شیء Promise، نمایانگر قراردادی است که در آینده می‌تواند مورد قبول واقع شود، یا رد گردد. بررسی این قرارداد، تنها یکبار می‌تواند رخ دهد (پذیرش یا رد آن). هنگامیکه این بررسی صورت گرفت (رد یا پذیرش آن و نه هردو)، یک callback برای اطلاع رسانی فراخوانی می‌گردد. سپس این callback می‌تواند یک Promise دیگر را سبب شود. به این ترتیب می‌توان Promiseها را زنجیر وار به یکدیگر متصل کرد. برای نمونه jQuery به صورت توکار از promises پشتیبانی می‌کند:
// returns a promise
$.get('http://site-url/0')    
.then(function(data) {
    // callback 1
    // returns a promise
    return $.get('http://site-url/1');   
})
.then(function(data) {
    // callback 2
    // returns a promise
    return $.post('http://site-url/2');
})
.then(function(data) {
    // callback 3
});
متد get در jQuery یک شیء promise را بازگشت می‌دهد. در ادامه می‌توان این نتیجه را توسط متد then، زنجیروار ادامه داد. متدی که به عنوان پارامتر به then ارسال می‌شود، یک callback بوده و پس از پایان کار promise قبلی رخ می‌دهد. آرگومانی که به این callback ارسال می‌شود، نتیجه‌ی promise قبلی است. در حین اعمال jQuery Ajax، این callback تنها زمانی فراخونی می‌شود که عملیات قبلی موفقیت آمیز بوده باشد و data ارائه شده، اطلاعاتی است که توسط response دریافتی از سرور، دریافت گردیده‌است.
در این حالت، هر callback حداقل سه کار را می‌تواند انجام دهد:
الف) یک promise دیگر را بازگشت دهد. نمونه آن‌را با return $.get در کدهای فوق ملاحظه می‌کنید.
ب) خاتمه عادی. همینجا کار promise با مقدار بازگشت داده شده، پایان می‌یابد.
ج) صدور یک استثناء. سبب برگشت خوردن و عدم پذیرش promise می‌شود.


استفاده از Promises در سایر کتابخانه‌ها

jQuery پیاده سازی توکاری از promises دارد؛ اما سایر کتابخانه‌ها، مانند AngularJS ایی که مثال زده شده چطور عمل می‌کنند؟
استانداردی به نام  +Promises/A جهت یک دست سازی پیاده سازی‌های promise در جاوا اسکریپت پیشنهاد شده‌است. jQuery نیمی از آن‌را پیاده سازی کرده‌است؛ اما کتابخانه‌ی دیگری به نام Q Library، پیاده سازی نسبتا مفصل‌تری را از این استاندارد ارائه می‌دهد. فریم ورک AngularJS نیز در پشت صحنه از همین کتابخانه برای پیاده سازی promises استفاده می‌کند.


آشنایی با کتابخانه Q

استفاده مقدماتی از Q همانند مثالی است که از jQuery ملاحظه کردید.
 Q.fcall(callback1)
.then(callback2);
اشیاء promise بازگشت داده شده توسط jQuery نیز توسط کتابخانه Q مورد پذیرش واقع می‌شوند:
Q.fcall(function() {
    return $.get('http://my-url');
})
.then(callback3);
علاوه بر این‌ها مفهومی به نام deferred objects نیز در کتابخانه‌ی Q پیاده سازی شده‌است:
function waitForClick() {
    var deferred = Q.defer();

$('#okButton').click(function() {
        deferred.resolve();
    });

$('#cancelButton').click(function() {
        deferred.reject();
    });

return deferred.promise;
}

Q.fcall(waitForClick)
.then(function() {
    //  ok button was clicked
}, function() {
    //  cancel button was clicked
});
توسط deferred objects می‌توان بررسی یک promise را به تاخیر انداخت. در مثال فوق، اولین callback فراخوانی شده به نام waitForClick، از اشیاء به تاخیر افتاده استفاده می‌کند. ابتدا توسط فراخوانی متد Q.defer، یک deferred object ایجاد می‌شود. در این بین اگر کاربر بر روی دکمه‌ی OK کلیک کرد، با فراخوانی deferred.resolve، این promise مورد پذیرش واقع خواهد شد و یا اگر کاربر بر روی دکمه‌ی cancel کلیک کند، با فراخوانی متد deferred.reject، این promise رد می‌گردد. نهایتا شیء promise توسط deferred.promise بازگشت داده خواهد شد.
در ادامه کار، اینبار متد then، دو callback را قبول می‌کند. Callback اول پس از پذیرش قرار داد و Callback دوم پس از رد قرار داد، فراخوانی خواهد گردید.
در رنجیره تعریف شده، اگر معادلی برای reject درنظر گرفته نشده باشد، مانند مثال ذیل:
 Q.fcall(myFunction1)
.then(success1)
.then(success2, failure1);
Q به دنبال نزدیک‌ترین متد callback گزارش خطای کار خواهد گشت. در این حالت متد failure1 در صورت شکست اولین promise فراخوانی خواهد شد.
همچنین اگر نتیجه‌ی success1 با شکست مواجه شود نیز failure1 فراخوانی می‌گردد. اما باید درنظر داشت که شکست success2، توسط failure1 مدیریت نمی‌شود.


Promises در AngularJS

در AngularJS امکانات کتابخانه Q توسط پارامتری به نام q$ در اختیار سرویس‌های برنامه قرار می‌گیرد (تزریق می‌شود):
var app = angular.module("myApp", []);
app.factory('dataSvc', function($http, $q){
  var basePath="api/books";
  getAllBooks = function(){
   var deferred = $q.defer();
 $http.get(basePath).success(function(data){
    deferred.resolve(data);
   }).error(function(err){
    deferred.reject("service failed!");
   });
   return deferred.promise;
  };
 
  return{
   getAllBooks:getAllBooks
  };
});
 
app.controller('HomeController', function($scope, $window, dataSvc){
 function initialize(){
   dataSvc.getAllBooks().then(function(data){
    $scope.books = data;
   }, function(msg){
    $window.alert(msg);
   });
 }
 
 initialize();
});
در اینجا اگر دقت کنید، مباحث و عملکرد آن دقیقا مانند قبل است. ابتدا یک deferred object با فراخوانی متد q.defer ایجاد شده است. سپس با استفاده از امکانات توکار http آن (بجای استفاده از jQuery Ajax)، کار فراخوانی یک restful service صورت گرفته است (مثلا فراخوانی یک ASP.NET Web API). در صورت موفقیت کار، متد deferred.resolve و در صورت عدم موفقیت، متد deferred.reject فراخوانی شده‌است. نهایتا این سرویس، یک deferred.promise را بازگشت می‌دهد.
اکنون در کنترلری که قرار است از این سرویس استفاده کند، متد then کتابخانه Q را ملاحظه می‌کنید که دو Callback متناظر resolve و reject مدیریت promise بازگشت داده شده را به همراه دارد. اگر عملیات Ajaxایی موفقیت آمیز باشد، شیء books را مقدار دهی می‌کند و اگر خیر، پیامی را به کاربر نمایش خواهد داد.


پشتیبانی مرورگرهای جدید از استاندارد Promise

در حال حاضر کروم 32 و نگارش‌های شبانه فایرفاکس، Promise را که جزئی از استاندارد JavaScript شده‌است، به صورت توکار و بدون نیاز به کتابخانه‌های جانبی، پشتیبانی می‌کنند.
if (window.Promise) { // Check if the browser supports Promises
 var promise = new Promise(function(resolve, reject) {
  //asynchronous code goes here
 });
}
در اینجا با فراخوانی window.Promise مشخص می‌شود که آیا مرورگر جاری از Promises پشتیبانی می‌کند یا خیر. سپس یک شیء promise ایجاد شده و این شیء توسط پارامترهای resolve و reject که هر دو تابع می‌باشند، کار مدیریت کدهای غیرهمزمان را انجام می‌دهد:
if (window.Promise) {
 console.log('Promise found');
 
 var promise = new Promise(function(resolve, reject) {
      // async
  if (result) {
   resolve(data);
  } else {
   reject('error');
  }  
 });
 
 promise.then(function(data) {
  console.log('Promise fulfilled.');
 }, function(error) {
  console.log('Promise rejected.');
 });
} else {
 console.log('Promise not available');
}
در مثال فوق ابتدا یک شیء Promise ایجاد شده است. این شیء استاندارد بوده و با کروم 32 قابل آزمایش است. سپس در callback ابتدایی آن می‌توان یک عملیات AJAX ایی را انجام داد. اگر نتیجه‌ی آن موفقیت آمیز بود، تنها کافی است پارامتر اول این callback را فراخوانی کنیم و اگر خیر، پارامتر دوم آن‌را. برای استفاده از این شیء Promise ایجاد شده، می‌توان از متد then استفاده کرد. این متد نیز در اینجا دو callback پذیرش و رد promise را می‌تواند دریافت کند. برای زنجیر کردن آن کافی است متد then، یک Promise دیگر را بازگشت دهد و از نتیجه‌ی آن در then بعدی استفاده گردد.
مطالب دوره‌ها
نگاهی به افزونه‌های کار با اسناد در RavenDB
توانمندی‌های RavenDB جهت کار با اسناد، صرفا به ذخیره و ویرایش آن‌ها محدود نمی‌شوند. در ادامه، مباحثی مانند پیوست فایل‌های باینری به اسناد، نگهداری نگارش‌های مختلف آن‌ها، حذف آبشاری اسناد و وصله کردن آن‌ها را مورد بررسی قرار خواهیم داد. تعدادی از این قابلیت‌ها توکار هستند و تعدادی دیگر توسط افزونه‌های آن فراهم شده‌اند.


پیوست و بازیابی فایل‌های باینری

امکان پیوست فایل‌های باینری نیز به اسناد 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();
                }
            }
کار متد store.DatabaseCommands.PutAttachment، ارسال اطلاعات یک استریم به سرور RavenDB است که تحت کلید مشخصی ذخیره خواهد شد. متد استاندارد System.IO.File.OpenRead روش مناسبی است برای دریافت استریم‌ها و ارسال آن به متد PutAttachment. در قسمت metadata این فایل، توسط شیء RavenJObject، یک دیکشنری از key-valueها را جهت درج اطلاعات اضافی مرتبط با هر فایل می‌توان مقدار دهی کرد. پس از آن، جهت انتساب این فایل ارسال شده به یک سند، تنها کافی است کلید آن‌را به خاصیت FileId انتساب دهیم.
در این حالت اگر به خروجی دیباگ سرور نیز دقت کنیم، مسیر ذخیره سازی این نوع فایل‌ها مشخص می‌شود:
 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);
                }
            }
فقط کافی است سند را یکبار Load کرده و سپس از متد store.DatabaseCommands.GetAttachment برای دستیابی به فایل پیوست شده استفاده نمائیم.


وصله کردن اسناد

سند سؤالات قسمت اول و پاسخ‌های آن، همگی داخل یک سند هستند. اکنون برای اضافه کردن یک آیتم به این لیست، یک راه، واکشی کل آن سند است و سپس افزودن یک آیتم جدید به لیست پاسخ‌ها و یا در این حالت، جهت کاهش ترافیک سرور و سریعتر شدن کار، 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..."})
                                                             }
                                                          });
                }
            }
برای وصله کردن اسناد از متد store.DatabaseCommands.Patch استفاده می‌شود. در اینجا ابتدا Id سند مورد نظر مشخص شده و سپس آرایه‌ای از تغییرات لازم را به صورت اشیاء PatchRequest ارائه می‌دهیم. در هر PatchRequest، خاصیت Type مشخص می‌کند که حین عملیات وصله کردن چه کاری باید صورت گیرد؛ برای مثال اطلاعات ارسالی اضافه شوند یا ویرایش و امثال آن. خاصیت Name، نام خاصیت در حال تغییر را مشخص می‌کند. برای مثال در اینجا می‌خواهیم به مجموعه پاسخ‌های یک سند، آیتم جدیدی را اضافه کنیم. خاصیت Value، مقدار جدید را دریافت خواهد کرد. این مقدار باید با فرمت JSON تنظیم شود؛ به همین جهت از متد توکار RavenJObject.FromObject برای اینکار استفاده شده است.


افزونه‌های RavenDB

قابلیت‌های ذکر شده فوق جهت کار با اسناد به صورت توکار در RavenDB مهیا هستند. این سیستم افزونه پذیر است و تاکنون افزونه‌های متعددی برای آن تهیه شده‌اند که در اینجا به آن‌ها Bundles گفته می‌شوند. برای استفاده از آن‌ها تنها کافی است فایل DLL مرتبط را درون پوشه Plugins سرور، کپی کنیم. دریافت آن‌ها نیز از طریق NuGet پشتیبانی می‌شود؛ و یا سورس آن‌ها را دریافت کرده و کامپایل کنید. در ادامه تعدادی از این افزونه‌ها را بررسی خواهیم کرد.


حذف آبشاری اسناد

 PM> Install-Package RavenDB.Bundles.CascadeDelete -Pre
فایل افزونه حذف آبشاری اسناد را از طریق دستور نیوگت فوق می‌توان دریافت کرد. سپس فایل Raven.Bundles.CascadeDelete.dl دریافتی را درون پوشه plugins کنار فایل exe سرور RavenDB کپی کنید تا قابل استفاده شود.
استفاده مهم این افزونه، حذف پیوست‌های باینری اسناد و یا حذف اسناد مرتبط با یک سند، پس از حذف سند اصلی است (که به صورت پیش فرض انجام نمی‌شود).
یک مثال:
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();
برای استفاده از آن باید از متد session.Advanced.GetMetadataFor استفاده کرد. در اینجا شیء post که دارای تعدادی کامنت است، مشخص می‌شود. سپس با مشخص سازی Raven-Cascade-Delete-Documents و ذکر Id کامنت‌های مرتبطی که باید حذف شوند، تمام این اسناد با هم پس از حذف post، حذف خواهند شد. همچنین دستور Raven-Cascade-Delete-Attachments سبب حذف فایل‌های مشخص شده با Id مرتبط با یک سند، می‌گردد.


نگهداری و بازیابی نگارش‌های مختلف اسناد

 PM> Install-Package RavenDB.Bundles.Versioning
فایل افزونه Versioning اسناد را از طریق دستور نیوگت فوق می‌توان دریافت کرد. سپس فایل dll دریافتی را درون پوشه plugins کنار فایل exe سرور RavenDB کپی کنید تا قابل استفاده شود. فایل Raven.Bundles.Versioning.dll باید در پوشه افزونه‌ها کپی شود و فایل Raven.Client.Versioning.dll به برنامه ما ارجاع داده خواهد شد.
با استفاده از قابلیت document versioning می‌توان تغییرات اسناد را در طول زمان، ردیابی کرد؛ همچنین حذف یک سند، این سابقه را از بین نخواهد برد.
 تنظیمات اولیه آن به این صورت است که توسط شیء VersioningConfiguration به سشن جاری اعلام می‌کنیم که چند نگارش از اسناد را ذخیره کند. اگر Exclude آن به true تنظیم شود، اینکار صورت نخواهد گرفت.
session.Store(new VersioningConfiguration
{
  Exclude = false,
  Id = "Raven/Versioning/DefaultConfiguration",
  MaxRevisions = 5
});
تنظیم Id به Raven/Versioning/DefaultConfiguration، سبب خواهد شد تا VersioningConfiguration فوق به تمام اسناد اعمال شود. اگر نیاز است برای مثال تنها به BlogPosts اعمال شود، این Id را باید به Raven/Versioning/BlogPosts تنظیم کرد.
بازیابی نگارش‌های مختلف یک سند، صرفا از طریق متد Load میسر است و در اینجا شماره Id نگارش به انتهای Id سند اضافه می‌شود. برای مثال "blogposts/1/revisions/1" به نگارش یک مطلب شماره یک اشاره می‌کند.
برای بدست آوردن سه نگارش آخر یک سند باید از متد ذیل استفاده کرد:
 var lastThreeVersions = session.Advanced.GetRevisionsFor<BlogPost>(post.Id, 0, 3);
مطالب
تفاوت Desktop Application با Web Application
در هنگام گفتگو با افراد مختلفی که در پروژه‌های توسعه نرم افزار، نقش‌های مختلفی را دارا می‌باشند، یکی از جالب‌ترین و اساسی‌ترین بحث‌ها تفاوت بین Desktop App و Web App می‌باشد، و این که پروژه بر اساس کدام مدل باید نوشته شود.

در اینترنت و در منابع معتبر، تفسیر‌های متفاوتی از این دو وجود دارد، که گاه دقیقا با نظر من یکی بوده و گاه تا 180 درجه بر عکس هستند، آنچه که در ادامه می‌خوانید می‌تواند لزوما نظر شما نباشد.
گروهی از افراد بر این باور هستند که اجرای برنامه در محیط مرورگر (ظاهر مرورگر و نه Sandbox آن)، یکی از ملاک‌های ما بین Desktop App  و Web App است، گروهی دیگر نیز اجرا شدن برنامه بر روی بستر اینترنت و یا شبکه‌ی محلی را جزو ملاک‌ها می‌دانند، و گروهی دیگر نیز زبان برنامه نویسی برنامه را ملاک می‌دانند، برای مثال اگر با HTML/JS باشد Web App است، اگر نه Desktop App است.
اما آنچه که در عمل می‌تواند تفاوت بین یک Desktop App را با یک Web App مشخص کند، رفتار و عملکرد خود آن برنامه است، نه بستر اجرای آن و این که آن رفتار منتج شده از چه کدی و چه زبان برنامه نویسی ای است.
اگر کمی دقیق به مطلب نگاه کنیم، می‌بینیم این که یک برنامه در چارچوب ظاهری یک مرورگر (نه Sandbox آن) اجرا شود، اصلا مقوله ای اهمیت دار نیست، کما این که برای مثال Silverlight اجازه می‌دهد، برنامه هم در داخل مرورگر و هم در بیرون از آن اجرا شود، و این کار با یک کلیک امکانپذیر است، آیا با همین یک کلیک برنامه از Web App به Desktop App تبدیل می‌شود یا بالعکس ؟
آیا یک برنامه مبتنی بر دلفی که تا همین یک ساعت پیش بر روی شبکه محلی در حال اجرا بوده، با انتقال پیدا کردن آن بر روی شبکه‌ی اینترنت، تبدیل به یک Web App می‌شود؟
آیا اگر ما با HTML/JS یک برنامه Native برای ویندوز فون بنویسیم که تک کاربره آفلاین باشد و اصلا سروری هم نداشته باشد، آیا Web App نوشته ایم ؟
اصلی‌ترین تفاوت مابین Web App و Desktop App که به تفاوت در عملکرد آنها و مزایا و معایب آنها منجر می‌شود، این است که انجام کارهایی که اپراتور با آنها در سمت کلاینت و سیستم مشتری سر و کار دارد، در کجا صورت می‌پذیرد؟
برای مثال در نظر بگیرید که یک دیتاگرید داریم که دارای Paging است، و ما از Page اول به Page بعدی می‌رویم، در یک Desktop App تنها اطلاعات از سرور گرفته می‌شود، و ترسیم خطوط و ستون‌ها و ردیف‌ها و ظاهر نمایشی دیتاگرید بر عهده کلاینت است، برای مثال اگر ستون قیمت داشته باشیم، و بخواهیم برای ردیف هایی که قیمت آنها زیر 10000 ریال است، قیمت به شکل سبز رنگ نمایش داده شود و برای بقیه ردیف‌ها به رنگ قرمز باشد، پردازش این مسئله و این if به عهده کلاینت است، اما در یک Web App، علاوه بر اطلاعات، تعداد زیادی tag‌های مختلف، مانند table - tr - td و ... نیز به همراه اطلاعات آورده می‌شوند، که وظیفه نمایش ظاهری اطلاعات را بر عهده دارند، و آن if مثال ما یعنی رنگ سبز و قرمز در سمت سرور مدیریت شده است، و کلاینت در اینجا نمایش دهنده‌ی آن چیزی است که به صورت آماده از سرور آورده شده است.
در برنامه‌های Desktop آنچه که در سمت سرور وجود دارد، برای مثال یک WCF Service یا ASP.NET Web API است که فقط به رد و بدل کردن اطلاعات می‌پردازد، اما در Web App‌ها در سمت سرور ASP.NET Web Forms، ASP.NET MVC و PHP وجود دارند که علاوه بر اطلاعات برای کلاینت شما ظاهر صفحات را نیز آماده می‌کنند، و ظاهر اصلی صفحات از سمت سرور به سیستم مشتری ارسال می‌شوند، اگر چه که ممکن است در سمت کلاینت تغییراتی را داشته باشند.
به هر میزان رفتار برنامه ما شبیه به حالت اول باشد، برنامه ما Desktop App بوده و به هر میزان برنامه ما به حالت دوم نزدیک‌تر باشد، برنامه ما Web App است.
مزیت اصلی Web App‌ها در عدم انداختن بار زیاد بر روی دوش کلاینت‌های بعضا نحیف بوده، و عملا کلاینت به علت این که کار خاصی را انجام نمی‌دهد، پیش نیاز نرم افزاری و یا سخت افزاری خاصی احتیاج ندارد، و این مورد Web App‌ها را به یک گزینه ایده آل برای وب سایت هایی تبدیل کرده است که با عموم مردم در ارتباطند، زیرا که امکان ارائه آسان برنامه وجود دارد و تقریبا همه می‌توانند از آن استفاده کنند.
با توجه به شناخت عموم از برنامه‌های Web App به توضیح بیشتر برنامه‌های Desktop App می‌پردازم.
مزیت اصلی Desktop App‌ها در سرعت عمل بالاتر(به علت این که فقط دیتا را رد و بدل می‌کند)، توانایی بیشتر در استفاده از منابع سیستمی مانند سرویس نوشتن، و امکانات محلی مانند ارائه Notification و ... است، و در کنار آن برای مثال یک Desktop App می‌تواند به نحوی طراحی شود که به صورت Offline نیز کار کند.
این مزیت‌ها باعث می‌شود که Desktop App‌ها گزینه ای مناسب برای برنامه‌های سازمانی باشند.
ضعفی که از گذشته در Desktop App‌ها وجود داشته است، که البته به معماری Desktop App بر نمی‌گردد، بلکه متاثر از امکانات است، عدم Cross Platform بودن آنها بوده است، تا آنجا که Desktop App در نظر خیلی از افراد همان نوشتن برنامه برای سیستم عامل ویندوز است.
با توجه به رویکرد جدی ای که در طول دو سال اخیر برای نوشتن برنامه Desktop App به شکل Cross Platform رخ داده است، خوشبختانه این مشکل حل شده است و اکنون لااقل دو راهکار جدی برای نوشتن یک برنامه Cross Platform با ویژگی‌های Desktop وجود دارد، که یکی از آنها راه حل‌های مبتنی بر HTML/JS است و دیگری راه حل‌های مبتنی بر C#/XAML
در راه حل‌های مبتنی بر HTML/JS در صورتی که شما برنامه را به شکل Web App طراحی نکرده باشید، و برای مثال در آن از ASP.NET Web Forms و ASP.NET MVC، PHP و ... استفاده نکرده باشید، می‌توانید یک خروجی کاملا Native با تمامی ویژگی‌های Desktop App برای انواع پلتفرم‌ها بگیرید.
استفاده از فریم ورک هایی که با طراحی Desktop App سازگار هستند، مانند Angular JS، Kendo UI و Ext JS، Jay-data و ... و استفاده از مدل طراحی Single Page Application می‌تواند سیستم کدنویسی ای ساده را فراهم آورد، که در آن شما با یک بار نوشتن برنامه می‌توانید خروجی اکثر پلتفرم‌های مطرح را داشته باشید، اعم از ویندوز فون، اندروید، iOS و ویندوز
امروزه حتی مرورگر‌ها با فراهم آوردن امکاناتی مانند Client side databases و Manifest based deployment اجازه نوشتن برنامه Desktop با HTML/JS را که حتی می‌تواند Offline کار کند را به شما ارائه می‌کنند.
در کنار این راهکار، استفاده از C#/XAML برای نوشتن برنامه برای اکثر پلتفرم‌های مطرح بازار اعم از اندروید، iOS و Windows Phone و ویندوز، نیز به عنوان راهکاری دیگر قابلیت استفاده را دارا است.
حرکت پر شتاب و پر انرژی جهانی برای توسعه Cross Platform Desktop Development، خوشبختانه توانسته است تا حد زیادی امتیاز نوشتن برنامه‌های Desktop را در سیستم‌های Enterprise بالا ببرد.
مطالب
3# آموزش سیستم مدیریت کد Git

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

(Working Tree (Directory: پوشه‏‌ی روتی است که فایل‏های پروژه در آن نگه‏داری می‏‌شود. این پوشه باید حاوی پوشه‌ای به نام git. باشد که محتویات این پوشه، در اصل Repository ما را تشکیل می‏دهند.

اشیا در Git:

برای درک بهتر عملکرد سیستم مدیریت کد Git بهتر است نگاهی به اجزای تشکیل دهنده آن داشته باشیم. به طور کلی Git دارای 4 نوع object است، که هر کدام وظیفه خاصی را به عهده دارند:

1)Tree: شیئ Tree دقیقا مانند دایرکتوری‏‌ها در یک سیستم مدیریت فایل است. در واقع tree‌ها ساختاری درختی را ایجاد می‏‌کنند تا وضیعت فایل‏ها و پوشه‌ها را در Repository حفظ نمایند. هر tree توسط یک کد منحصر به فرد SHA-1 نام گذاری می‌شود.

2)(BLOB(Binary large object: اگر با سیستم‏های مدیریت داده نظیر SQL Server کار کرده باشید قطعا با BLOB آشنایی دارید. BLOB‌ها در واقع چیزی نیستند جز یک مجموعه از بایت‏‏ها که می‏توانند حاوی هر چیزی باشند (نظیر عکس، فایل متنی،  فایلهای اجرایی و...) در Git فایل‏ها به صورت BLOB و به شکل کامل ذخیره می‏‌شوند. همچنین مقدار هش شده محتویات فایل‏ها با استفاده از SHA-1 در خود فایل ذخیره می‏‌شود. به این ترتیب در صورت تغییر در فایل، مقدار هش جدید با مقدار موجود در فایل فرق کرده و Git متوجه می‏‌شود که فایل دچار تغییر شده است. نکته قابل توجه این است که بر خلاف بسیاری از سیستم‏های مدیریت کد، در هر بار تغییر فایل، Git تنها تغییرات را ذخیره نمی‏‌کند بلکه از کل محتوا یک snapshot می‏‌گیرد. شاید به نظر بسیاری تهیه این ‏snapshotهای فراوان باعث زیاد شدن حجم Repository شود، اما Git هوشمندانه تنها فایل‏‌هایی را مجددا ذخیره می‌نماید که مقدار آن‏ها تغییر کرده است. در غیر این صورت یک نشانگر به فایل موجود در snapshot جدید ایجاد می‏کند.

3)Commit: این شئ، یک  snapshot از وضعیت فعلی Working Tree است. در واقع با هر با دستور commit این object ایجاد شده و حداقل حاوی اطلاعات زیر است:

مقدار هش درختی که به آن اشاره می‏کند

نام ثبت کننده دستور commit

توضیحی درباره علت ایجاد commit

خود commit نیز توسط یک کد منحصر به فرد SHA-1 شناخته می‏‌شود.

4)Tag: چون کار کردن با کد‏های هش commit ممکن مشکل باشد، می‌توان از تگ‏ها به عنوان نامی برای commit استفاده نمود. خود تگ می‏‌تواند حاوی توضیحاتی باشد.

آشنایی با (Stage(Index:

هر فایل قبل از آنکه بخواهد در Repository توسط دستور commit ذخیره شود باید ابتدا به Stage آورده شود. در این حالت Git تغیرات فایل را دنبال کرده و سپس می‏‌توان توسط دستور commit فایل را در Repository وارد کرد. بنابراین ذخیره یک فایل در Git دارای سه مرحله است:

Modified : یعنی فایل تغییر کرده اما به stage اضافه نشده است

Staged: فایل تغییر کرده به stage اضافه شده است.

Commited: فایل در Repository ذخیره شده است.

head:

اشاره‏‌گری است که به آخرین شئ commit اشاره می‏‌کند. هر Repository می‏تواند یک head برای هر شاخه‏‏‌ی مختلف داشته باشد؛ اما در هر لحظه تنها یک head به عنوان head جاری شناخته می‏‌شود که معمولا آن را با حروف بزرگ یعنی HEAD مشخص می‏‌کنند.

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

مطالب
مفاهیم پایه سیستم های کنترل نسخه؛ قسمت اول : گیت
در این مقاله با دو سیستم کنترل نسخه  git  و  SVN  آشنا شده و تفاوت‌های آن‌ها را برای تازه‌کاران بررسی می‌کنیم. ایده اولیه نوشتن این مقاله زمانی بود که برای یک پروژه‌ای، اعضای تیم ما دور هم جمع شده و در مورد ابزارهای مورد استفاده بحث کردند و یک عده از گیت و عده‌ای از SVN صحبت می‌کردند. بر این شدم که مقاله‌ای نوشته و ابتدا به معرفی آن‌ها و سپس به مزایا و معایب هر کدام بپردازیم.  
امروزه، استفاده از سیستم‌های کنترل نسخه ( Version Control System ) رواج زیادی پیدا کرده است. این سیستم‌ها به شما اجازه می‌دهند تا تغییراتی را که در پروژه ایجاد می‌شوند، ضبط و ثبت کرده تا از تغییراتی که در سطح پروژه اتفاق می‌افتد آگاه شوید. با ذکر یک نمونه این تعریف را باز میکنم:
شما به صورت تیمی در حال انجام یک پروژه هستید و باید نسبت به تغییراتی که اعضای تیم در یک پروژه می‌دهند، آگاه شوید. هر برنامه نویس بعد از انجام تغییرات باید این تغییرات را در سیستم کنترل نسخه به روز کند تا بتوان به سوالات زیر پاسخ داد:
 آیا اگر در بین راه به مشکل برخوردید می‌توانید پروژه خود را به یک یا چند گام عقب‌تر برگردانید؟ آیا می‌توانید به هر یک از اعضاء تیم دسترسی‌هایی را به قسمت هایی از پروژه تعیین کنید؟ می‌توانید تفاوت فایل‌های تغییر یافته را بیابید؟ آیا میتوان خطاهای یک برنامه را گزارش داد و به بحث در مورد آن پرداخت؟ چه کسی کدها را تغییر داده است؟ روند کار و تغییرات به چه صورت است؟ (این مورد برای به روز کردن نمودارهای burndown در توسعه چابک می‌تواند بسیار مفید باشد.)
پی نوشت: نه تنها در یک تیم بلکه بهتر هست در یک کار انفرادی هم از این سیستم‌ها استفاده کرد تا حداقل بازبینی روی پروژه‌های شخصی خود هم داشته باشیم.

سیستم کنترل گیت: این سیستم در سال 2005 توسط لینوس توروالدز خالق لینوکس معرفی شد و از آن زمان تاکنون یکی از پر استفاده‌ترین سیستم‌های کنترل نسخه شناخته شده است. ویکی پدیا گیت را به این شکل تعریف می‌کند: «یک سیستم بازبینی توزیع شده با تاکید بر جامعیت داده‌ها، سرعت و پشتیبانی جهت توزیع کار.»
از معروف‌ترین سیستم‌های هاستینگ که از گیت استفاده می‌کنند، می‌توان به گیت هاب اشاره کرد.
اکثر سیستم‌های هاستینگ گیت، دو حالت را ارائه می‌دهند:
عمومی : در این حالت کدهای شما به عموم بازدیدکنندگان نمایش داده می‌شود و دیگران هم می‌توانند در تکمیل و ویرایش کدهای شما مشارکت کنند و این امکان به صورت رایگان فراهم است. سیستم گیت هاب به دلیل محبوبیت زیادی که دارد، در اکثر اوقات انتخاب اول همه کاربران است.
خصوصی: در این حالت کد متعلق به شما، یا شرکت یا تیم نرم افزاری شماست و غیر از افراد تعیین شده، شخص دیگری به کدهای شما دسترسی ندارد. اکثر سیستم‌های مدیریتی این مورد را به صورت premium پشتیبانی می‌کنند. به این معنا که باید اجاره آن را به طور ماهانه پرداخت کنید. سیستم گیت هاب ماهی پنج دلار بابت آن دریافت می‌کند. سیستم دیگری که در این زمینه محبوبیت دارد سیستم BitBucket هست که که اگر تیم شما کوچک است و در نهایت پنج نفر هستید، می‌توانید از حالت خصوصی به طور رایگان استفاده کنید ولی اگر اعضای تیم شما بیشتر شد، باید هزینه‌ب اجاره آن را که از 10 دلار آغاز می‌گردد، به طور ماهیانه پرداخت کنید.
پی نوشت: میتوانید از سیستم‌های متن باز رایگان هم که قابل نصب بر روی هاست ها هم هستند استفاده کنید که در این حالت تنها هزینه هاست یا سرور برای شما می‌ماند.

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

Fork: هر کاربری که قصد تغییر را بر روی سورس کدی، داشته باشد، ابتدا باید پروژه‌ی نویسنده اصلی پروژه را به یک مخزنی که متعلق به خودش هست انتقال دهد. به این عمل Fork کردن می‌گویند. حال کاربر تغییرات خودش را اعمال کرده و لازم هست که این تغییرات با پروژه‌ی اصلی که به آن Master می‌گوییم ادغام شوند. بدین جهت کاربر فرمان pull request را می‌دهد تا به نویسنده‌ی اصلی پروژه این موضوع اطلاع داده شود و نویسنده‌ی اصلی در صورت صلاحدید خود آن را تایید کند. 

Branching یا شاخه بندی: نویسنده‌ی مخزن اصلی می‌تواند با مفهومی با نام شاخه بندی کار کند. او با استفاده از این مفهوم، پروژه را به قسمت یا شاخه‌های مختلف تقسیم کرده و همچنین با ایجاد دسترسی‌های مختلف به کاربران اجازه تغییرات را بدهد. به عنوان مثال بخش‌های مختلف پروژه از قبیل بخش منطق برنامه، داده ها، رابط کاربری و ... می‌تواند باشد. بعد از انجام تغییرات روی یک شاخه می‌توانید درخواست merge ادغام شدن یا کل پروژه را داشته باشید. در عمل شاخه بندی، هیچ کدام از شاخه‌های بر روی یک دیگر تاثیر یا دخالتی ندارند و حتی می‌توانید چند شاخه را جدا از بخش master با یکدیگر ادغام کنید.

به غیر از ارتباط خط فرمانی که میتوان با گیت هاب برقرار کرد، میتوان از یک سری ابزار گرافیکی خارجی هم جهت ایجاد این ارتباط، استفاده کرد:
GitHub For Windows : نسخه‌ی رسمی است که از طرف خود گیت هاب تهیه گردیده است و استفاده از آن بسیار راحت است. البته یک مشکل کوچک در دانلود آن وجود دارد که دانلود آن از طریق یک برنامه‌ی جداگانه صورت گرفته و اصلا سرعت خوبی جهت دانلود ندارد.
Visual Studio .Net : (+ ) خود ویژوال استودیو شامل سیستمی به اسم Microsoft Git Provider است که در بخش تنظیمات می‌توانید آن را فعال کنید (به طور پیش فرض فعال است) و به هر نوع سیستم گیتی می‌توانید متصل شوید. تنها لازم است که آدرس Url گیت را وارد کنید.
SourceTree: از آن دست برنامه‌های محبوبی است که استفاده آسانی دارد و خودم به شخصه از آن استفاده می‌کنم. شامل دو نسخه‌ی ویندوز و مک است و میتوانید با چندین سیستم گیت مثل «گیت هاب» و «بیت باکت» که در بالا به آن‌ها اشاره شد، به طور همزمان کار کند.