نظرات مطالب
شروع به کار با EF Core 1.0 - قسمت 10 - استفاده از امکانات بومی بانک‌های اطلاعاتی
رفع محدودیت «خروجی کوئری SQL، تنها باید معادل یکی از کلاس‌های موجودیت‌های شما باشد» در نگارش 2.1
در نگارش 2.1 مفهوم جدیدی به نام Query Types ارائه شده‌است که امکان نگاشت به خروجی‌های خاص بانک اطلاعاتی مانند Viewها و یا رویه‌های ذخیره شده را میسر می‌کند که این خروجی‌ها عموما مستقل از فیلدهای جداول و موجودیت‌های تعریف شده‌ی در برنامه هستند.
برای مثال فرض کنید یک View ویژه را بر اساس جدول و یا جداول بانک اطلاعاتی خود طراحی کرده‌اید:
using (var db = new BloggingContext())
{
   db.Database.ExecuteSqlCommand(
         @"CREATE VIEW View_BlogPostCounts AS 
             SELECT Name, Count(p.PostId) as PostCount from Blogs b
             JOIN Posts p on p.BlogId = b.BlogId
             GROUP BY b.Name");
}
خروجی این View که دو ستون name و PostCount را به همراه دارد، متناظر با موجودیت‌های اصلی برنامه نیست. برای تهیه نگاشتی به آن، ابتدا کلاس مدل متناظر با این ستون‌های بازگشتی را تهیه می‌کنیم:
public class BlogPostsCount
{
    public string BlogName { get; set; }
    public int PostCount { get; set; }
}

سپس برای معرفی آن به Context باید دو مرحله انجام شود:
الف) این کلاس به صورت DbQuery در Context معرفی می‌شود:
public class BloggingContext : DbContext
{
    public DbQuery<BlogPostsCount> BlogPostCounts { get; set; }
ب) در متد OnModelCreating همین Context، نگاشت این DbQuery به View یاد شده توسط متد ToView انجام می‌شود:
   protected override void OnModelCreating(ModelBuilder modelBuilder)
   {
      modelBuilder
           .Query<BlogPostsCount>().ToView("View_BlogPostCounts")
           .Property(v => v.BlogName).HasColumnName("Name");
    }
متد ToView الزاما نیازی به یک view ندارد. مفهوم آن صرفا یک خروجی فقط خواندنی است. برای مثال حتی در اینجا یک جدول بانک اطلاعاتی را هم می‌توانید ذکر کنید. اما مفهوم آن غیرقابل تغییر بودن خروجی کوئری‌های آن است. بنابراین باید دقت داشت که در اینجا مهم نیست که کلاس نگاشت تعریف شده دارای کلید هست یا خیر و ارجاعی از این کلاس را نمی‌توان در کلاس‌های موجودیت‌های اصلی مورد استفاده قرار داد.
از متد Property به این جهت استفاده شده‌است که در کلاس BlogPostsCount، خاصیت BlogName، متناظر با هیچکدام از ستون‌های بازگشتی View تعریف شده نیست. به همین جهت با استفاده از این متد مشخص کرده‌ایم که این خاصیت باید به کدام ستون بازگشتی، نگاشت شود.
و در آخر کوئری گرفتن از این DbQuery تعریف شده به صورت زیر است:
using (var db = new BloggingContext())
{
   var postCounts = db.BlogPostCounts.ToList();

مثال کامل این نکته
نظرات مطالب
اعمال تزریق وابستگی‌ها به مثال رسمی ASP.NET Identity
در مثال بالا هر لاگین کاربر حداقل 9 بار کاربر همراه با رل هاش از دیتابیس فراخوانی میشه اگر ورود دو مرحله فعال باشه حدودا 28 بار میشه ، روش پیش فرض که آی دی رو string پیاد سازی کرده رو بررسی کردم چنین مشکلی نداشت. در کلاس ApplicationUserManager متد FindByIdAsync  رو بصورت زیر تغییر بدید می‌تونید تعداد فراخوانی را بررسی کنید: 
      public override Task<ApplicationUser> FindByIdAsync(int userId)
        {
                     return base.FindByIdAsync(userId);
        }

        public override Task<ApplicationUser> FindByNameAsync(string userName)
        {
            return base.FindByNameAsync(userName);
        }
در کدهای  Identity به دفعات از متود  FindByIdAsync  استفاده شده و فرض بر این بوده که دفعات بعد از کش DbContext اسفاده می‌شود.
در سورس UserStore متود FindByIdAsync  از یک متد واسطه  به نام GetUserAggregateAsync استفاده کرده :
public virtual Task<TUser> FindByIdAsync(TKey userId)
        {
            ThrowIfDisposed();
            return GetUserAggregateAsync(u => u.Id.Equals(userId));
        }
     protected virtual async Task<TUser> GetUserAggregateAsync(Expression<Func<TUser, bool>> filter)
        {
            TKey id;
            TUser user;
            if (FindByIdFilterParser.TryMatchAndGetId(filter, out id))
            {
                user = await _userStore.GetByIdAsync(id).WithCurrentCulture();
            }
            else
            {
                user = await Users.FirstOrDefaultAsync(filter).WithCurrentCulture();
            }
            if (user != null)
            {
                await EnsureClaimsLoaded(user).WithCurrentCulture();
                await EnsureLoginsLoaded(user).WithCurrentCulture();
                await EnsureRolesLoaded(user).WithCurrentCulture();
            }
            return user;
        }
وقتی پیاده سازی آی دی براساس int باشه متد FindByIdFilterParser.TryMatchAndGetId درست عمل نمی‌کنه و به جای فراخوانی GetByIdAsync که پشت صحنه از FindAsync و قابلیت فراخوانی از کش رو داره از FirstOrDefaultAsync استفاده می‌کنه و باعث فراخوانی مجدد از دیتابیس می‌شود.
راه حلی که من استفاده کردم پیاده سازی UserStore و تحریف متد FindByIdAsync  :
    public class MyUserStore
        :UserStore<ApplicationUser, CustomRole, int, CustomUserLogin, CustomUserRole, CustomUserClaim>
    {

        private DbSet<ApplicationUser> _myUserStore;
        public MyUserStore(ApplicationDbContext context)
            : base(context)
        {
            _myUserStore = (DbSet<ApplicationUser>) context.Set<ApplicationUser>();

        }

        public override Task<ApplicationUser> FindByIdAsync(int userId)
        {
           return  _myUserStore.FindAsync(userId);
        }
  
    }
}
 همچنین در کلاس SmObjectFactory کد زیر :
               ioc.For<IUserStore<ApplicationUser, int>>()
                .HybridHttpOrThreadLocalScoped()
                .Use<UserStore<ApplicationUser, CustomRole, int, CustomUserLogin, CustomUserRole, CustomUserClaim>>();
با این کد جایگزین شود :
ioc.For<IUserStore<ApplicationUser, int>>()
                    .HybridHttpOrThreadLocalScoped()
                 .Use<MyUserStore>();

مطالب
پیاده سازی Default Dependency Injection در AngularJS 1.x
 در این مقاله شما را با روشی آشنا خواهم کرد که در عین سادگی، کارآیی زیادی در پروژه‌های  AngularJS خواهد داشت.
برای همه ما پیش آماده است که خیلی از Injection‌های Controller‌های AngularJS به صورت مشترک بوده ولی مجبور شده‌ایم این Injection‌ها را در هر Controller تکرار کنیم. کدهای زیر را مشاهده کنید. در این کد یک سری از injection‌ها به صورت مشترک در این ۴ Controller تکرار شده است.
app.controller('ctrl1',['$scope','$rootscope','$location','$route','api','delete','notify',ctrl1]);
...
app.controller('ctrl2',['$scope','$rootscope','$location','$route','api','delete','notify','chart',ctrl2]);
...
app.controller('ctrl3',['$scope','$rootscope','$location','$route','api','delete','notify','pulling',ctrl3]);
...
app.controller('ctrl4',['$scope','$rootscope','$location','$route','api','delete','notify','chart','report',ctrl4]);
در پروژه‌های بزرگ که تعداد Controller‌ها بیش از حد می‌باشد همیشه تعدادی Injection مشترک وجود دارد و مدیریت این Injection‌ها در همه کنترل‌ها و مخصوصا کنترل‌های جدید که به پروژه اضافه میکنیم سخت می‌شود و گاهی از نظم خارج می‌شود مخصوصا وقتی که تعداد Developer‌ها در پروژه زیاد باشند.
در این روش که نوعی Trick ساده Javascript هست به شما در مدیریت Injection‌ها کمک میکند.
خوب ابتدا همه Injectionهای مشترک Controller‌ها را شناسایی می‌کنیم و یه آرایه تعریف میکنیم و همه Injection‌های مشترک را مرتب در این آرایه قرار می‌دهیم.
var injection=['$scope','$rootscope','$location','$route','api','delete','notify'];
با استفاده از تابع زیر مابقی Injection‌های مختص هر Controller را پیاده سازی می‌کنیم.
function injectionHandle() {    
    var _injection=angular.copy(injection);
    for(var i=0;i<arguments.length;i++){
        _injection.push(arguments[i]);        
    }
    return _injection;
}
توضیح تابع: در خط اول یک Copy از آرایه را تهیه می‌کنیم تا در دفعات بعد هم این آرایه قابل استفاده باشد. arguments در داخل تابع به رشته Injectionهای ارسال شده به تابع و تابع Controller اشاره دارد. با این روش می‌توانیم به صورت نامحدود Injection‌ها را به تابع ارسال کنیم. در داخل حلقه به Copy متغیر injection همه Injection‌های ارسالی به تابع را push میکنیم. نهایتا این تابع آرایه‌ای از injection‌های مشترک و Injectionهای مختص هر Controller و خود تابع Controller را بر میگرداند.
در مرحله بعدی در تعریف Controller‌ها تابع injectionHandle را همراه با Injection‌های مختص آن  Controller را صدا میزنیم.
در کد زیر نحوه استفاده از این روش را مشاهده میکنید:
app.controller('ctrl1', injectionHandle(ctrl1));
...
app.controller('ctrl2', injectionHandle('chart',ctrl2));
...
app.controller('ctrl3', injectionHandle('pulling',ctrl3));
...
app.controller('ctrl4', injectionHandle('chart','report',ctrl4));
همانطور که مشاهده کردید، با این روش خیلی راحتتر می‌توانید Injection‌های مشترک را مدیریت کنید. اگر قرار باشد Injection جدیدی را به همه Controller‌ها اضافه کنید، کافیست آن را در آرایه injection درج کنید.
مطالب
شروع به کار با Aurelia
در این مطلب قصد داریم نحوه‌ی راه اندازی و شروع به کار با Aurelia را توضیح دهیم. برای شروع ابتدا باید Git را نصب کنیم. زیرا می‌خواهیم از jspm برای نصب محتویات Aurelia استفاده کنیم و برای کار کردن با jspm باید Git بر روی سیستم نصب باشد. در صورتیکه Git نصب نباشد، زمان init کردن jspm با خطای زیر رو به رو می‌شویم :

پس از نصب Git اطمینان حاصل کنید که NodeJs ، npm و jspm نیز بر روی سیستم شما نصب باشند. در این قسمت گفته‌ایم که چگونه از این «اطمینان» آگاه شوید.

حال نوبت به ساخت اولین پروژه‌ی MVC ما می‌رسد. یک پروژه MVC جدید با نام دلخواه خودتان در مسیر دلخواه خودتان ایجاد کنید. با خط فرمان، در ریشه‌ی پروژه دستور زیر را اجرا کنید:

jspm init

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

حالا نوبت به نصب محتویات Aurelia می‌باشد. برای این کار دستورات زیر را اجرا کنید : 

jspm install aurelia-framework
jspm install aurelia-bootstrapper
با صادر کردن دستورات بالا، jspm تمامی فایل‌های مورد نیاز Aurelia را در پوشه‌ی jspm_packages قرار می‌دهد.

توجه داشته باشید، اگر دستورات بالا به درستی اجرا و تکمیل شوند، باید پس از پایان هر دستور، پیام زیر را در انتهای خروجی مشاهده کنید:
 

پس از این کارها، فایل Layout را باز کنید و کدهای آن را به صورت زیر تغییر دهید:
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Aurelia - www.dotnettips.info</title>
</head>
<body aurelia-app>
    <div>
        @RenderBody()
    </div>
    <script src="~/jspm_packages/system.js"></script>
    <script src="~/config.js"></script>
    <script>
        System.import("aurelia-bootstrapper");
    </script>
</body>
</html>
سپس در ریشه‌ی برنامه یک فایل جاوااسکریپت را با نام app ایجاد کنید و کدهای زیر را در آن قرار دهید:
export class App {
    
}
حالا به یک View، برای این کار نیاز داریم. در همان ریشه‌ی سایت یک فایل html را با نام app ایجاد کنید و کدهای زیر را در آن قرار دهید:
<template>
    <h3>www.dotnettips.info</h3>
</template>
پس از سپری کردن این 3 مرحله، برنامه‌ی خود را اجرا کنید. باید خروجی زیر را مشاهده کنید:

در بخش‌های بعدی در مورد کدهای فوق و همچنین به سایر مباحث دیگر Aurelia می‌پردازیم.

نکته‌ی تکمیلی

زمانیکه می‌خواهید از دستوارت jspm استفاده کنید، باید به ریشه‌ی برنامه مراجعه کنید. حال اگر پوشه‌های تودرتوی زیادی داشته باشید، این رفت و آمد‌ها زمانبر و خسته کننده خواهند شد. برای حل این مشکل کافیست روی پروژه، راست کلیک کنید و گزینه‌ی Open Folder in File Explorer را انتخاب کنید تا ریشه‌ی پروژه باز شود. حالا  کافیست در فضای خالی Windows Explorer کلید Shift را گرفته و راست کلیک کنید. حالا یک آیتم جدید با نام Open command window here ظاهر شده است. کافیست روی آن کلیک کنید. CMD در ریشه‌ی سایت باز خواهد شد.


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

برای استفاده از آی‌دنتیتی‌سرور، ابتدا آن را از مخزن گیت‌هاب، بارگذاری می‌کنیم  و سپس برای پروژه، یک Application جدید در IIS ایجاد می‌کنیم. 
دقت داشته باشید که IdentityServer    از SSL  و بستر امن استفاده می‌کند که تنظیمات ساخت Certificate را می‌توانید از اینجا فرا بگیرید. 
با توجه به پشتیبانی گسترده‌ی این پروژه از OpenID و OAuth2   مطالعه‌ای مختصر در این موارد به درک فرایند اهراز هویت توسط  آی دنتیتی سرور بسیار کمک خواهد کرد.
پس از راه اندازی SSL  و تنظیمات Certificate مربوط به آن می‌توانید شروع به راه اندازی سرور خود کنید. راه اندازی اولیه سرور تنظیمات مربوط به بانک اطلاعاتی، نکات ریزی دارد که بخش کلی از آن اینجا آمده است. 
برای شروع به استفاده از سرور و درک چگونگی عملکرد آن نیاز دارید تا مدیر سرور را نصب کنید؛ تا هم بتوانید کاربر تعریف کنید و هم نقش‌ها (Roles)  و دسترسی‌ها را مدیریت کنید. نگارش مدیر آی‌دنتیتی‌سرور نیز از اینجا قابل دسترسی می‌باشد. 
پس از نصب آی‌دنتیتی‌سرور باید تنظیمات مربوط به ذخیره سازی اطلاعات آن را انجام دهید که  آی‌دنتیتی‌سرور پیاده سازی خوبی برای Entity Framework دارد که می‌توانید با نصب آن همه‌ی کارهای ذخیره سازی در بانک اطلاعاتی را به EF بسپارید. البته برای ذخیره‌ی یوزر می‌توان از حالت InMemory هم استفاده کرد که در  نسخه‌ی مثال  یک کاربر با نام bob و رمز bob در داخل کد نویسی تعریف شده بود، که می‌توان برای پروژه‌های کوچک همان را توسعه داد. 
در سطح بانک هم آی‌دنتیتی‌سرور از دو بانک اطلاعاتی، استفاده می‌کند؛ یکی برای ذخیره‌ی تنظیمات سرور و دیگری برای ذخیره‌ی اطلاعات هویتی. 
مزیت بزرگ آی‌دنتیتی‌سرور در اعتبار سنجی جدای از پیاده سازی‌های فراوان انجام شده برای محیط‌های مختلف و در قابلیت اعتبار سنجی دو طرفه‌ی آن می‌باشد. 
یعنی هم سمت سرور و هم سمت کلاینت و هم سرویس‌هایی که از  آی‌دنتیتی‌سرور استفاده می‌کنند، باید اعتبار سنجی شوند و همه چیز به یک رمز و نام کاربری ساده خلاصه نمی‌شود.
در زمان نگارش این متن، نسخه‌ی 2 نسخه‌ی پایدار ارائه شده است و نسخه‌ی سه در مرحله تست می‌باشد. البته پیاده سازی‌هایی هم از نسخه‌ی 3 در محیط‌های مختلف مثل MVC  و WEB API ارائه شده است؛ ولی هنوز به پایداری لازم نرسیده است.
مطالب
Performance در AngularJS قدم سوم
خیلی خوشحالم که تا این مرحله، این مقاله‌ها را دنبال می‌کنید. در مقالات قبل مسائل ساده و مهمی در بحث Performance مطرح شد. در این مقاله می‌خواهم قدم سوم در بهبود Performance را توضیح دهم که رعایت کردن این مسائل می‌تواند کمک زیادی در بهبود عملکرد برنامه‌های مبتنی بر AngularJS داشته باشد.

scope؟
همه‌ی برنامه نویسان و توسعه دهندگان، یکی از اولین مفاهیمی را که در AngularJS یاد می‌گیرند، scope هست. اما scope چیست؟ به صورت خیلی ساده می‌توان گفت scope مشخص کننده‌ی حوزه متغیر‌ها و توابعی هست که قرار است در View تاثیر داشته باشند. کد زیر را مشاهده کنید:
<div>نام و نام خانوادگی: {{name}}</div>
<div>معدل: {{avg()}}<div>
و کد سمت controller
scope.nums=[19,20,17,16,15,18,19];
scope.name='بهنام محمدی';
scope.avg= function(){
  return scope.nums.reduce(function(previousValue, currentValue) {
      return previousValue + currentValue;
   })/scope.nums.length;
}
و اما خروجی نهایی
نام و نام خانوادگی: بهنام محمدی
معدل:17.71
خوب چون ما در قسمت controller به صورت scope.name و scope.avg عمل کرده‌ایم، می‌توانیم در View به صورت name و avg از این متغیر‌ها استفاده کنیم. در نتیجه اگر ما در controller، به جای scope.name بنویسیم name و یا به جای scope.avg بنویسیم avg به مشکل بر می‌خوریم؛ چون قسمت View ما متغیر‌های داخل scope را در View دخیل می‌کند و متغیر‌های داخل scope توسط Watcher‌ها رصد می‌شود.

خوب سؤال، همه چیز که عالی هست پس مشکل در کجاست؟
مشکل در متغیر scope.nums هست! به کد زیر توجه کنید:
var nums=[19,20,17,16,15,18,19];
scope.name='بهنام محمدی';
scope.avg= function(){
  return nums.reduce(function(previousValue, currentValue) {
      return previousValue + currentValue;
   })/nums.length;
}
فکر کنم متوجه تفاوت این کد با کد بالایی شده‌اید. اما کدام کد درست است؟ یا بهتر بگویم کدام کد بر روی Performance تاثیر مناسبی دارد؟ کد پایینی Performance بالایی دارد. دلیل این موضوع این است وقتی ما از nums در View هیچ استفاده‌ای نمی‌کنیم، بهتر است به صورت var nums تعریف شود. در کد بالایی که این متغیر به صورت scope.nums تعریف شده بود، با اینکه در View استفاده نشده بود، ولی توسط Watcher AngularJS در هر لحظه رصد می‌شود و این کار باعث کندی و کاهش عملکرد AngularJS خواهد شد. بنابراین در کل متغیرهایی را که در View استفاده نمی‌کنید، به صورت var test استفاده نمایید تا Watcher AngularJS این متغیر‌ها را رصد نکند.
امیدوارم از این مقاله لذت برده باشید. منتظر مقاله بعدی من باشید.

مطالب
بررسی متد های یک طرفه در WCF
در WCF به صورت پیش فرض متد‌ها به صورت Request-Response هستند. این بدین معنی است که هر زمان درخواستی از سمت کلاینت به سرور ارسال شود تا زمانی که پاسخی از سمت سرور به کلاینت برگشت داده نشود، کلاینت منتظر خواهد ماند. برای مثال:
پروژه ای از نوع Wcf Service App می‌سازیم و یک سرویس با یک متد که خروجی آن نیز void است خواهیم داشت. به صورت زیر:
    [ServiceContract]
    public interface ISampleService
    {
        [OperationContract]
        void Wait();
    }
پیاده سازی Contract بالا:
public class SampleService : ISampleService
    {
        public void Wait()
        {
            Thread.Sleep( new TimeSpan( 0, 1, 0 ) );
        }
    }
  در متد Wait، به مدت یک دقیقه اجرای برنامه سمت سرور را متوقف می‌کنیم. حال در یک پروژه از نوع Console App، سرویس مورد نظر را اضافه کرده و متد Wait آن را فراخوانی می‌کنیم. به صورت زیر:
class Program
    {
        static void Main( string[] args )
        {
            SampleService.SampleServiceClient client = new SampleService.SampleServiceClient();

            Console.WriteLine( DateTime.Now );

            client.Wait();

            Console.WriteLine( DateTime.Now );

            Console.ReadKey();
        }
    }
همان طور که می‌بینید قبل از فراخوانی متد Wait زمان جاری سیستم را نمایش داده و سپس بعد از فراخوانی دوباره زمان مورد را نمایش می‌دهیم. در مرحله اول با خطای زیر مواجه خواهیم شد:


دلیل اینکه Timeout Exception پرتاب شد این است که به صورت پیش فرض مقدار خاصیت sendTimeout برابر 59  ثانیه است، در نتیجه قبل از اینکه پاسخی از سمت سرور به کلاینت برگشت داه شود این Exception رخ می‌دهد. برای حل این مشکل کافیست در فایل app.config کلاینت در قسمت تنظیمات Binding ، تغییر زیر را اعمال کنیم:
 <basicHttpBinding>
     <binding name="BasicHttpBinding_ISampleService" sendTimeout="0:2:0"/>
 </basicHttpBinding>
حال خروجی به صورت زیر است:


مشخص است که تا زمانی که عملیات سمت سرور به پایان نرسد،(یا توجه به اینکه خروجی متد سمت سرور void است) اجرای برنامه در کلاینت نیز متوقف خواهد بود(اختلاف زمان‌های بالا کمی بیش از یک دقیقه است).

در این مواقع زمانی که باید متدی سمت سرور فراخوانی شود و قرار نیست که خروجی نیز در اختیار کلاینت قرار دهد بهتر است که از متد‌های یک طرفه استفاده نماییم. متد‌های یک طرفه یا یه اصطلاح OneWay، هیچ پاسخی را به کلاینت برگشت نمی‌دهند و بلافاصله بعد از فراخوانی، کنترل اجرای برنامه را در اختیار کلاینت قرار خواهند داد. برای تعریف یک متد به صورت یک طرفه کافیست به صورت زیر عمل نماییم(مقدار خاصیت IsOneWay را در OperationContractAttribute برابر true خواهیم کرد):
    [ServiceContract]
    public interface ISampleService
    {
        [OperationContract( IsOneWay = true )]
        void Wait();
    }
حال اگر سرویس سمت کلاینت را به روز کرده و برنامه را اجرا کنیم خروجی به صورت زیر تغییر می‌کند:

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

مطالب
یکپارچه سازی TortoiseSVN و YouTrack
پیش نیاز
اگر در مورد TortoiseSVN و سورس کنترل اطلاعات پایه ندارید، کتاب  مدیریت فایلهای یک پروژه نرم افزاری با استفاده از Subversion  آقای نصیری را مطالعه کنید و همچنین سیستم پیگیری خطای  YouTrack را نگاهی بیاندازید (البته اگر اطلاعی ندارید).

مقدمه
هنگام کار روی یک پروژه، باگ ها، وظیفه‌ها و موضوعاتی به شما واگذار می‌شود که باید انها را انجام دهید. هنگام commit کردن تغییرات، برای مشخص شدن اینکه تغییرات مربوط به کدام Bug-Id بوده است بود است باید سیستم Bug/Issue Tracker رو با سورس کنترل یکپارچه کنیم. 

یکپارچه سازی TortoiseSVN و YouTrack
1- روی یک نسخه کاری پروژه راست کلیک، از منوی TortoiseSVN گزینه Properties را انتخاب کنید.

گزینه Properties در TortoiseSVN

2- از پنجر باز شده دکمه New، گزینه Other را انتخاب کنید. در پنجره باز شده از منوی کشویی مربوط به Property Name، مقادیر خصلت‌های زیر را تنظیم کنید:
bugtraq:url : آدرس YouTrack Sever که به این صورت وارد می‌شود: %http://localhost:8080/issue/%BUGID
bugtraq:message : درو اقع الگویی پیامی هست که برای نگهداری Bug-Id استفاده می‌شود و باید شامل کلمه %BUGID% باشد. مثلا: %Issue: %BUGID
bugtraq:number : مقدار این خصلت را false وارد کنید؛ چون Bug-Idهای‌های YouTrack می‌توانند شامل عدد و حروف باشند.

دیالوگ Propeties


بعد از اینکه این سه خصلت را مقداردهی کرید، تغییرات را Commit کنید. همانطور که می‌بینید یک Textbox (بالا، سمت راست) اضافه شده که محل وارد کردن Bug-Id مربوط به تغییرات است. از این پس، می‌توانید Bug-Id یا Issue-Id‌های مربوط به هر تغییرات را در آن Textbox وارد کنید.


همچنین تغییرات در پلاگین AnkhSVN در ویژال استودیو نیز اعمال می‌شود:


اکنون، در متن commitها شماره Bud-Id نیز ذکر شده است.


نکته 1: اگر YouTrack روی یک سرور نصب هست، بجای localhost نام کامپیوتر سرور یا آی پی آن را وارد کنید. پورت 8080 نیز بصورت پیش فرض است و اگر هنگام نصب آن را تغییر داده اید، اینجا نیز آنرا تغییر دهید.
نکته 2: خصلت bugtraq:message یک الگوی پیام از شما می‌گیرد؛ یعنی الگو را تحت هر شکلی می‌توان وارد کرد. بعنوان مثال الگو را به این شکل وارد کنید: "برای مشاهده جزئیات بیشتر به Bug-Id شماره %BUGID% مراجعه کنید."
نکته 3: اگر خصلت bugtraq:number مقدارش true باشد، برای وارد کردن Bug-Id فقط از عدد می‌توانید استفاده کنید. بصورت پیش فرض مقدار این خصلت true است.
نکته 4: می‌توانید این تنظیمات را در یک فایل Export کنید و در بقیه پروژه ها، با یک مرحله و بسادگی آنرا Import کنید.
خصلت‌های دیگری نیز می‌توان برروی مخزن کد اعمال کرد که از حوزه این مقاله خارج است. همچنین تنظمیات اختیاری جانبی دیگری نیز برای یکپارچه سازی وجود دارند. برای دیدن این تنظمیات روی نسخه کاری راست کلیک، از منوی TortoiseSVN گزینه Properties را انتخاب کنید و از پنجره باز شده روی دکمه New و گزینه ( Bugtraq (Issue tracker integration  را انتخاب کنید.

برای اطلاعات بیشتر در مورد این تنظیمات، داکیومنت یکپارچه سازی با سیستم‌های Bug tracking / Issue Tracking  را مطالعه کنید. 
مطالب
مروری بر مفاهیم مقدماتی NoSQL
هدف از این مبحث، آشنایی با مفاهیم پایه‌ای اغلب بانک‌های اطلاعاتی NoSQL است که به صورت مشترکی در تمام آن‌ها بکار رفته است. برای مثال بانک‌های اطلاعاتی NoSQL چگونه مباحث یکپارچگی اطلاعات را مدیریت می‌کنند؟ نحوه ایندکس نمودن اطلاعات در آن‌ها چگونه است؟ چگونه از اطلاعات کوئری می‌گیرند؟ الگوریتم‌های محاسباتی مانند MapReduce چیستند و چگونه در اینگونه بانک‌های اطلاعاتی بکار رفته‌‌اند؟ همچنین الگوهای Sharding و Partitioning  که در اغلب بانک‌های اطلاعاتی NoSQL مشترکند، به چه نحوی پیاده سازی شده‌اند.


لیست مشترکات بانک‌های اطلاعاتی NoSQL

قبل از اینکه بخواهیم وارد ریز جزئیات بانک‌های اطلاعاتی NoSQL شویم، نیاز است لیست و سرفصلی از مفاهیم اصلی و مشترک بین اینگونه بانک‌های اطلاعاتی را تدارک ببینیم که شامل موارد ذیل می‌شود:

الف) Non-Relational یا غیر رابطه‌ای
از کلمه NoSQL عموما اینطور برداشت می‌شود که در اینجا دیگر خبری از SQL نویسی نیست که در عمل برداشت نادرستی است. شاید جالب باشد که بدانید، تعدادی از بانک‌های اطلاعاتی NoSQL از زبان SQL نیز به عنوان اینترفیسی برای نوشتن کوئری‌های مرتبط، پشتیبانی می‌کنند.
کلمه NoSQL بیشتر به Non-Relational یا غیر رابطه‌ای بودن اینگونه بانک‌های اطلاعاتی بر می‌گردد. مباحثی مانند مدل‌های داده‌ای نرمال شده، اتصالات و Join جداول، در دنیای NoSQL وجود خارجی ندارند.

ب) Non-schematized/schema free یا بدون اسکیما
مفهوم مهم و مشترک دیگری که در بین بانک‌های اطلاعاتی NoSQL وجود دارد، بدون اسکیما بودن اطلاعات آن‌ها است. به این معنا که با حرکت از رکورد یک به رکورد دو،  ممکن است با دو ساختار داده‌ای متفاوت مواجه شوید.

ج) Eventual consistency یا عاقبت یک دست شدن
عاقبت یک دست شدن، به معنای دریافت دستوری از شما و نحوه پاسخ دادن به آن (یا حتی پاسخ ندادن به آن) از طرف بانک اطلاعاتی NoSQL است. برای مثال، زمانیکه یک رکورد جدید را اضافه می‌کنید، یا اطلاعات موجودی را به روز رسانی خواهید کرد، اغلب بانک‌های اطلاعاتی NoSQL این دستور را بسیار سریع دریافت و پردازش خواهند کرد. اما تفاوت است بین دریافت پیام و پردازش واقعی آن در اینجا.
اکثر بانک‌های اطلاعاتی NoSQL، پردازش و اعمال واقعی دستورات دریافتی را با یک تاخیر انجام می‌دهند. به این ترتیب می‌توان خیلی سریع به بانک اطلاعاتی اعلام کرد که چه می‌خواهیم و بانک اطلاعاتی بلافاصله مجددا کنترل را به شما بازخواهد گرداند. اما اعمال و انتشار واقعی این دستور، مدتی زمان خواهد برد.

د) Open source یا منبع باز بودن
اغلب بانک‌های اطلاعاتی NoSQL موجود، منبع باز هستند که علاوه بر بهره بردن از مزایای اینگونه پروژه‌ها، استفاده کنندگان سورس باز دیگری را نیز ترغیب به استفاده از آن‌ها کرده‌اند.

ه) Distributed یا توزیع شده
هرچند امکان پیاده سازی توزیع شده بانک‌های اطلاعاتی رابطه‌ای نیز وجود دارد، اما نیاز به تنظیمات قابل توجهی برای حصول این امر می‌باشد. در دنیای NoSQL، توزیع شده بودن جزئی از استاندارد تهیه اینگونه بانک‌های اطلاعاتی است و بر اساس این مدل ذهنی شکل گرفته‌اند. به این معنا که اطلاعات را می‌توان بین چندین سیستم تقسیم کرد، که حتی این سیستم‌ها ممکن است فواصل جغرافیایی قابل توجهی نیز با یکدیگر داشته باشند.

و) Web scale یا مناسب برای برنامه‌های تحت وب پر کاربر
امروزه بسیاری از کمپانی‌های بزرگ اینترنتی، برای مدیریت تعداد بالایی از کاربران همزمان خود، مانند فیس‌بوک، یاهو، گوگل، Linkedin، مایکروسافت و غیره، نیاز به بانک‌های اطلاعاتی پیدا کرده‌اند که باید در مقابل این حجم عظیم درخواست‌ها و همچنین اطلاعاتی که دارند، بسیار بسیار سریع پاسخ دهند. به همین جهت بانک‌های اطلاعاتی NoSQL ابداع شده‌اند تا بتوان برای این نوع سناریوها پاسخی را ارائه داد.
و نکته مهم دیگر اینجا است که خود این کمپانی‌های بزرگ اینترنتی، بزرگترین توسعه دهنده‌های بانک‌های اطلاعاتی NoSQL نیز هستند.



نحوه مدیریت یکپارچگی اطلاعات در بانک‌های اطلاعاتی NoSQL

مدیریت یکپارچگی اطلاعات بانک‌های اطلاعاتی NoSQL به علت ذات و طراحی توزیع شده آن‌ها، با نحوه مدیریت یکپارچگی اطلاعات بانک‌های اطلاعاتی رابطه‌ای متفاوت است. اینجا است که تئوری خاصی به نام CAP مطرح می‌شود که شامل یکپارچگی یا Consistency به همراه Availability یا دسترسی پذیری (همیشه برقرار بودن) و partition tolerance یا توزیع پذیری است. در تئوری CAP مطرح می‌شود که هر بانک اطلاعاتی خاص، تنها دو مورد از سه مورد مطرح شده را می‌تواند با هم پوشش دهد.
به این ترتیب بانک‌های اطلاعاتی رابطه‌ای عموما دو مورد C و P یا یکپارچگی (Consistency) و partition tolerance یا میزان تحمل تقسیم شدن اطلاعات را ارائه می‌دهند. اما بانک‌های اطلاعاتی NoSQL از این تئوری، تنها دو مورد A و P را پوشش می‌دهند (دسترسی پذیری و توزیع پذیری مطلوب).
بنابراین مفهومی به نام ACID که در بانک‌های اطلاعاتی رابطه‌ای ضامن یکپارچگی اطلاعات آن‌ها است، در دنیای NoSQL وجود خارجی ندارد. کلمه ACID مخفف موارد ذیل است:
Atomicity، Consistency، Isolation و Durability
ACID در بانک‌های اطلاعاتی رابطه‌ای تضمین شده است. در این نوع سیستم‌ها، با ایجاد تراکنش‌ها، مباحث ایزوله سازی و یکپارچگی اطلاعات به نحو مطلوبی مدیریت می‌گردد؛ اما دنیای NoSQL، دسترسی پذیری را به یکپارچگی ترجیح داده است و به همین جهت پیشتر مطرح شد که مفهوم «Eventual consistency یا عاقبت یک دست شدن» در این نوع بانک‌های اطلاعاتی در پشت صحنه بکار گرفته می‌شود. یک مثال دنیای واقعی از عاقبت یک دست شدن اطلاعات را حتما در مباحث DNS مطالعه کرده‌اید. زمانیکه یک رکورد DNS اضافه می‌شود یا به روز خواهد شد، اعمال این دستورات در سراسر دنیا به یکباره و همزمان نیست. هرچند اعمال این اطلاعات جدید در یک نود شبکه ممکن است آنی باشد، اما پخش و توزیع آن در سراسر سرورهای DNS دنیا، مدتی زمان خواهد برد (گاهی تا یک روز یا بیشتر).
به همین جهت است که بانک‌های اطلاعاتی رابطه‌ای در حجم‌های عظیم اطلاعات و تعداد کاربران همزمان بالا، کند عمل می‌کنند. حجم اطلاعات بالا است، مدتی زمان خواهد برد تا تغییرات اعمال شوند، و چون مفهوم ACID در این نوع بانک‌های اطلاعاتی تضمین شده است، کاربران باید مدتی منتظر بمانند و نمونه‌ای از آن‌ها را با dead lockهای شایع، احتمالا پیشتر بررسی یا تجربه کرده‌اید. در مقابل، بانک‌های اطلاعاتی NoSQL بجای یکپارچگی، دسترسی پذیری را اولویت اول خود می‌دانند و نه یکپارچگی اطلاعات را. در یک بانک اطلاعاتی NoSQL، دستور ثبت اطلاعات دریافت می‌شود (این مرحله آنی است)، اما اعمال نهایی آن آنی نیست و مدتی زمان خواهد برد تا تمام اطلاعات در کلیه سرورها یک دست شوند.



نحوه مدیریت Indexing اطلاعات در بانک‌های اطلاعاتی NoSQL

اغلب بانک‌های اطلاعاتی NoSQL تنها بر اساس اطلاعات کلیدهای اصلی جداول آن‌ها index می‌شوند (البته نام خاصی به نام «جدول»، بسته به نوع بانک اطلاعاتی NoSQL ممکن است متفاوت باشد، اما منظور ظرف دربرگیرنده تعدادی رکورد است در اینجا). این ایندکس نیز از نوع clustered است. به این معنا که اطلاعات به صورت فیزیکی، بر همین مبنا ذخیره و مرتب خواهند شد.
یک مثال: بانک اطلاعاتی NoSQL خاصی به نام Hbase که بر فراز Hadoop distributed file system طراحی شده است، دقیقا به همین روش عمل می‌کند. این فایل سیستم، تنها از روش Append only برای ذخیره سازی اطلاعات استفاده می‌کند و در آن مفهوم دسترسی اتفاقی یا random access پیاده سازی نشده است. در این حالت، تمام نوشتن‌ها در بافر، لاگ می‌شوند و در بازه‌های زمانی متناوب و مشخصی سبب باز تولید فایل‌های موجود و مرتب سازی مجدد آن‌ها از ابتدا خواهند شد. دسترسی به این اطلاعات پس از تکمیل نوشتن، به علت مرتب سازی فیزیکی که صورت گرفته، بسیار سریع است. همچنین مصرف کننده سیستم نیز چون بلافاصله پس از ثبت اطلاعات در بافر سیستم، کنترل را به دست می‌گیرد، احساس کار با سیستمی را خواهد داشت که بسیار سریع است.
به علاوه Indexهای دیگری نیز وجود دارند که بر اساس کلیدهای اصلی جداول تولید نمی‌شوند و به آن‌ها ایندکس‌های ثانویه یا secondary indexes نیز گفته می‌شود و تنها تعداد محدودی از بانک‌های اطلاعاتی NoSQL از آن‌ها پشتیبانی می‌کنند. این مساله هم از اینجا ناشی می‌شود که با توجه به بدون اسکیما بودن جداول بانک‌های اطلاعاتی NoSQL، چگونه می‌توان اطلاعاتی را ایندکس کرد که ممکن است در رکورد دیگری، ساختار متناظر با آن اصلا وجود خارجی نداشته باشد.



نحوه پردازش Queries در بانک‌های اطلاعاتی NoSQL

بانک‌های اطلاعاتی NoSQL عموما از زبان کوئری خاصی پشتیبانی نمی‌کنند. در اینجا باید به اطلاعات به شکل فایل‌هایی که حاوی رکوردها هستند نگاه کرد. به این ترتیب برای پردازش و یافتن اطلاعات درون این فایل‌ها، نیاز به ایجاد برنامه‌هایی است که این فایل‌ها را گشوده و بر اساس منطق خاصی، اطلاعات مورد نظر را استخراج کنند. گاهی از اوقات زبان SQL نیز پشتیبانی می‌شود ولی آنچنان عمومیت ندارد. الگوریتمی که در این برنامه‌ها بکار گرفته می‌شود، Map Reduce نام دارد.
Map Reduce به معنای نوشتن کدی است، با دو تابع. اولین تابع اصطلاحا Map step یا مرحله نگاشت نام دارد. در این مرحله کوئری به قسمت‌های کوچکتری خرد شده و بر روی سیستم‌های توزیع شده به صورت موازی اجرا می‌شود. مرحله بعد Reduce step نام دارد که در آن، نتیجه دریافتی حاصل از کوئری‌های اجرا شده بر روی سیستم‌های مختلف، با هم یکی خواهند شد.
این روش برای نمونه در سیستم Hadoop بسیار مرسوم است. Hadoop دارای یک فایل سیستم توزیع شده است (که پیشتر در مورد آن بحث شد) به همراه یک موتور Map Reduce توکار. همچنین رده دیگری از بانک‌های اطلاعاتی NoSQL، اصطلاحا Wide column store نام دارند (مانند Hbase) که عموما به همراه Hadoop بکارگرفته می‌شوند. موتور Map Reduce متعلق به Hadoop بر روی جداول Hbase اجرا می‌شوند.
به علاوه Amazon web services دارای سرویسی است به نام Elastic map reduce یا EMR که در حقیقت مجموعه‌ی پردازش ابری است که بر مبنای Hadoop کار می‌کند. این سرویس قادر است با بانک‌های اطلاعاتی NoSQL دیگر و یا حتی بانک‌های اطلاعاتی رابطه‌ای نیز کار کند.
بنابراین MapReduce، یک بانک اطلاعاتی نیست؛ بلکه یک روش پردازش اطلاعات است که فایل‌ها را به عنوان ورودی دریافت کرده و یک فایل را به عنوان خروجی تولید می‌کند. از آنجائیکه بسیاری از بانک‌های اطلاعاتی NoSQL کار عمده‌اشان، ایجاد و تغییر فایل‌ها است، اغلب جداول اطلاعات آن‌ها ورودی و خروجی‌های معتبری برای یک موتور Map reduce به حساب می‌آیند.
در این بین، افزونه‌ای برای Hadoop به نام Hive طراحی شده است که با ارائه HiveSQL، امکان نوشتن کوئری‌هایی SQL مانند را بر فراز موتور‌های Map reduce ممکن می‌سازد. این افزونه با Hive tables خاص خودش و یا با Hbase سازگار است.



آشنایی مقدماتی با مفاهیمی مانند الگوهای Sharding و Partitioning در بانک‌های اطلاعاتی NoSQL

Sharding (شاردینگ تلفظ می‌شود) یک الگوی تقسیم اطلاعات بر روی چندین سرور است که اساس توزیع شده بودن بانک‌های اطلاعاتی NoSQL را تشکیل می‌دهد. این نوع تقسیم اطلاعات، از کوئری‌هایی به نام Fan-out پشتیبانی می‌کند. به این معنا که شما کوئری خود را به نود اصلی ارسال می‌کنید و سپس به کمک موتور‌های Map reduce، این کوئری بر روی سرورهای مختلف اجرا شده و نتیجه نهایی جمع آوری خواهد شد. به این ترتیب تقسیم اطلاعات، صرفا به معنای قرار دادن یک سری فایل بر روی سرورهای مختلف نیست، بلکه هر کدام از این سرورها به صورت مستقل نیز قابلیت پردازش اطلاعات را دارند.
امکان تکثیر و همچنین replication هر کدام از سرورها نیز وجود دارد که قابلیت بازیابی سریع و مقاومت در برابر خرابی‌ها و مشکلات را افزایش می‌دهند.
از آنجائیکه Shardها را می‌توان در سرورهای بسیار متفاوت و گسترده‌ای از لحاظ جغرافیایی قرار داد، هر Shard می‌تواند همانند مفاهیم CDN نیز عمل کند؛ به این معنا که می‌توان Shard مورد نیاز سروری خاص را در محلی نزدیک‌تر به او قرار داد. به این ترتیب سرعت عملیات افزایش یافته و همچنین بار شبکه نیز کاهش می‌یابد.
مطالب
آموزش TypeScript #2
در این پست قصد دارم به بررسی چند نکته که از پیش نیاز‌های کار با TypeScript  است بپردازم. همان طور که در پست قبلی مشاهده شد بعد از دانلود و نصب افزونه  TypeScript در VS.Net یک Template به نام Html Application With TypeScript به Installed Template اضافه خواهد شد. بعد از انتخاب این قسمت شما به راحتی می‌توانید در هر فایل با پسوند ts کد‌های مورد نظر به زبان TypeScript را نوشته و بعد از build پروژه این کد‌ها تبدیل به کد‌های JavaScript خواهند شد. بعد کافیست فایل مورد نظر را با استفاده از تک Script در فایل خود رفرنس دهید. دقت کنید که پسوند فایل حتما باید js باشد(به دلیل اینکه بعد از build پروژه فایل‌های ts تبدیل به js می‌شوند).
برای مثال:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title>TypeScript HTML App</title>
    <link rel="stylesheet" href="app.css" type="text/css" />
    <script src="app.js"></script>
</head>
<body>
    <h1>Number Type in TypeScript</h1>
    <div id="content"/>
</body>
</html>

اما اگر یک پروژه وب نظیر Asp.Net MVC داشته باشیم و می‌خواهیم یک یا چند فایل که حاوی کد‌های typeScript هستند را به این پروژه اضافه کرده و از آن‌ها در صفخات وب خود استفاده کنیم باید به این صورت عمل نمود:
بعد از اضافه کردن فایل‌های مورد نیاز، پروژه مورد نظر را Unload کنید. بعد به صورت زیر فایل پروژه(csproj) رو با یک ویرایشگر متنی باز کنید:

در این مرحله باید دو قسمت اضافه شود. یک بخش  ItemGroup است که هر فایلی که در پروژه شما دارای پسوند ts است باید در این جا تعریف شود. در واقع این قسمت فایل هایی را که باید کامپایل شده تا در نهایت تبدیل به فایل‌های JavaScript شوند را مشخص می‌کند.
بخش دوم target است که مراحل Build پروژه را برای این فایل‌های مشخص شده تعیین می‌کند. برای مثال:

همان طور که می‌بینید در قسمت ItemGroup تمام فایل‌های با پسوند ts در پروژه include شده اند. در قسمت target دستور کامپایل این فایل‌ها تعیین شد. اما نکته مهم این است که TypeScript به صورت پیش فرض از ECMAScript 3 در هنگام کامپایل کد‌ها استفاده می‌کند.(ECMAScript 3 در سال 1999 منتشر شد و تقریبا با تمام مرورگرها سازگاری دارد اما از امکانات جدید در Javascript پشتیبانی نمی‌کند). اگر قصد دارید که از ECMAScript 5 در هنگام کامپایل کد‌ها استفاده نمایید کافیست دستور زیر را اضافه نمایید:
--target ES5
مثال:

اما به این نکته دقت داشته باشید که ECMAScript 5 در سال 2009 منتشر شده است در نتیجه فقط با مرورگرهای جدید سازگار خواهد بود و ممکن است کد‌های شما در مرورگرهای قدیمی با مشکل مواجه شود.
مرورگرهایی که از ECMAScript 5 پشتیبانی می‌کنند عبارتند از:
  • IE 9 و نسخه‌های بعد از آن؛
  • FireFox 4 و نسخه‌های بعد از آن؛ 
  • Opera 12 و نسخه‌های بعد از آن؛ 
  • Safari 5.1 و نسخه‌های بعد از آن؛ 
  • Chrome 7 و نسخه‌های بعد از آن.
ادامه دارد...