نظرات مطالب
آشنایی با TransactionScope
می توان یک خاصیت به صورت زیر به اینترفیس IUnitOfWork اضافه کرد. این خاصیت از نوع کلاس Database است که در فضای نام System.Data.Entity قرار دارد.
    public interface IUnitOfWork
    {        
        void Dispose();
 DbSet<T> Set<T>() where T : class;   int SaveChanges(); Database Database { get; } }
کلاس DbContext خود دارای خاصیتی به نام Database هست. در نتیجه نیاز به پیاه سازی مجدد ندارد.
مطالب
آموزش LINQ بخش ششم - عملگرهای پرس و جو قسمت اول
عملگرهای استاندارد پرس و جو

در یک طبقه بندی کلی، عملگرهای پرس و جو بر اساس ورودی و خروجی آنها به سه دسته تقسیم می‌شوند:
1- نتیجه‌ی توالی ورودی، بصورت یک توالی، به خروجی ارسال می‌شود.
2- نتیجه‌ی توالی ورودی، بصورت یک عنصر یکتا و واحد به خروجی ارسال می‌شود.
3- اثری از ورودی در توالی خروجی وجود ندارد (این عملگرها عناصر خودشان را تولید می‌کنند).

دسته‌ی آخر شاید کمی عجیب به نطر برسد. این عملگرها هیچ توالی ورودی را دریافت نمی‌کنند. مثلا می‌توان از طریق این عملگر‌ها، یک توالی از اعداد صحیح را تولید کرد.
تقسیم بندی عملگرهای پرس و جو بر اساس عملکرد به صورت زیر می‌باشد : 
  • محدود کننده (Restriction)
where
  • بازتابی (Projection)
Select,SelectMany 
  • جداکننده (Partitioning)
Take,Skip,TakeWhile,SkipWhile 
  • مرتب سازی (Ordering)
OrderBy,OrderByDescending,ThenBy,ThenByDescending,Reverse 
  • گروه بندی (Grouping)
GroupBy 
  • مجموعه (Set)
Concat,Union,Intersect,Except 
  • تبدیل (Conversion)
ToArray,ToList,ToDictionary,ToLookup,OfType,Cast 
  • عنصر(Element)
First,FirstOrDefault,Last,LastOrDefalt,Single,SingleOrDefault 
  • عنصر در (ElementAt)
ElementAtOrDefault,DefaultIfEmpty 
  • تولید (Generation)
Empty,Range,Report 
  • کمی (Quantifier)
Any,All,Contains,SequenceEqual 
  • مجموعه (Aggregate)
Count,LongCount,Sum,Min,Max,Average,Aggregate 
  • اتصال (Join)
Join,GroupJoin,Zip 

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

عملگرهای محدود کننده (Restriction Operators)
این عملگرها یک توالی ورودی را دریافت و یک توالی محدود شده یا به بیان دیگر فیلتر شده را تولید می‌کنند. عناصر توالی خروجی، عناصری هستند که با فیلتر اعمال شده مطابقت دارند.
Where
این عملگر، عناصری را به خروجی ارسال می‌کند که با گزاره‌ی (Predicate) تعریف شده مطابقت داشته باشند.
نکته : گزاره (Predicate) تابعی است که اگر شرط آن تامین شود، مقدار true و در غیر اینصورت مقدار false را باز می‌گرداند.
مثال : 
 Ingredient[] ingredients =
{
   new Ingredient{Name = "Sugar", Calories=500},
   new Ingredient{Name = "Egg", Calories=100},
   new Ingredient{Name = "Milk", Calories=150},
   new Ingredient{Name = "Flour", Calories=50},
   new Ingredient{Name = "Butter", Calories=200},
};

IEnumerable<Ingredient> query = ingredients.Where(x => x.Calories >= 200);
foreach (var ingredient in query)
{
   Console.WriteLine(ingredient.Name);
}
در کد فوق از عملگر where استفاده شده است. گزاره‌ی (x=>x.Calories>=200) به ازای هر غذایی که کالری آن مساوی یا بزرگتر از 200 باشد، مقدار true را باز می‌گرداند.
خروجی کد بالا:
 Sugar
Butter
عملگر where امضای دیگری دارد که اندیس عنصر ورودی توالی را نیز می‌پذیرد. در مثال قبل، اندیس Sugar برابر 0 و اندیس Butter برابر 4 است. پرس و جوی زیر خروجی مشابه مثال قبل را تولید می‌کند.
 IEnumerable<Ingredient> query = ingredients.Where((ingredient, index) => ingredient.Name == "Sugar" || index == 4);
گزاره نوشته شده در این پرس و جو  از نوع <Func<Ingredient,int,bool خواهد بود و پارامتر int، اندیس عنصر در توالی ورودی می‌باشد.

پیاده سازی توسط عبارت‌های پرس و جو
 در روش عبارت‌های پرس و جو، کلمه‌ی کلیدی where به‌همراه یک عبارت منطقی در پرس و جو ظاهر می‌شود:
 IEnumerable<Ingredient> gueryExpression =
from i in ingredients
where i.Calories >= 200
select i;


عملگرهای بازتاب (Projection Operators)

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

Select
عملگر پرس و جوی select هر عنصر توالی ورودی را به یک عنصر در توالی خروجی تبدیل می‌کند. تعداد عناصر ورودی و خروجی در این حالت یکسان می‌باشند.
پرس و جوی زیر عناصر توالی ورودی Ingredient را به عناصر رشته‌ای در توالی خروجی بازتاب می‌کند. عبارت Lambda تعریف شده، نحوه‌ی بازتاب عناصر را مشخص می‌کند (هر عنصر ingredient به یک عنصر رشته‌ای بازتاب می‌شود):
 IEnumerable<string> query = ingredients.Select(x => x.Name);
  می‌توان توالی خروجی با عناصر صحیح را نیز تولید کرد:  
 IEnumerable<int> query = ingredients.Select(x => x.Name.Length);

در عملیات بازتاب می‌توان یک شیء جدید را در توالی خروجی ایجاد کرد. در کد زیر عناصر Ingredient به یک عنصر جدید از نوع IngredientNameAndLenght بازتاب شده است.
class IngredientNameAndLength
{
    public string Name { get; set; }
    public int Length { get; set; }
    public override string ToString()
    {
      return Name + " " + Length;
    }
}

IEnumerable<IngredientNameAndLength> query = ingredients.Select(x =>
new IngredientNameAndLength
{
   Name = x.Name,
   Length = x.Name.Length
});
پرس و جوی بالا را می‌توان به شکل نوع‌های بی نام نیز بازنویسی کرد. باید دقت شود که نوع بازگشتی این پرس و جو باید از نوع var باشد.
var query = ingredients.Select(x =>
new
{
   Name = x.Name,
   Length = x.Name.Length
});
خروجی کد بالا به شکل زیر است :
{ Name = Sugar, Length = 5 }
{ Name = Egg, Length = 3 }
{ Name = Milk, Length = 4 }
{ Name = Flour, Length = 5 }
{ Name = Butter, Length = 6 }

پیاده سازی توسط عبارت‌های پرس و جو

کلمه‌ی کلیدی select در عبارت‌های پرس و جو، به شکل زیر استفاده می‌شود:
var query = from i in ingredients
select new
{
    Name=i.Name,
    Length=i.Name.Length
};

SelectMany 
برعکس دستور select که به ازای هر عنصر در توالی ورودی، یک عنصر را در توالی خروجی بازتاب می‌کرد، دستور SelectMany ممکن است تعداد عناصر کمتر و یا بیشتری را در توالی خروجی بازتاب کند (انتخاب مقادیر یک مجموعه از مجموعه‌ی دیگر).
عبارت Lambda نوشته شده در عملگر Select، یک مقدار را باز می‌گرداند. اما عبارت Lambda نوشته شده در عملگر SelectMany، یک توالی فرزند (Child Sequence) را ایجاد می‌کند. توالی فرزند ممکن است حاوی تعداد مختلفی از عناصر به ازای هر عنصر در توالی ورودی باشد.
در مثال زیر عبارت Lambda یک توالی فرزند از کاراکتر‌ها ایجاد می‌کند (یک کاراکتر به ازای هر حرف از هر عنصر توالی ورودی). به‌طور مثال عنصر ورودی Sugar، پس از پردازش توسط  عبارت Lambda، یک توالی فرزند با 5 عنصر 's','u','g','e','r' فراهم می‌کند. هر رشته‌ی در توالی Ingredient می‌تواند تعداد حروف متفاوتی داشته باشد. در نتیجه عبارت Lambda، توالی‌های فرزندی با طول‌های مختلف ایجاد می‌کند.
مثال:
string[] ingredients = {"Sugar","Egg","Milk","Flour","Butter"};
IEnumerable<char> query = ingredients.SelectMany(x => x.ToCharArray());
foreach (var item in query)
{
   Console.WriteLine(item);
}
خروجی مثال بالا :
 S
u
g
a
r
E
g
g
M
i
l
k
F
l
o
u
r
B
u
t
t
e
r

پیاده سازی توسط عبارت‌های پرس و جو

در روش عبارت‌های پرس و جو یک عبارت (clause) اضافی from برای تولید یک توالی فرزند به کار برده می‌شود. خروجی کد زیر مشابه کد قبلی است:
 string[] ingredients = {"Sugar","Egg","Milk","Flour","Butter"};
IEnumerable<char> query2 = from i in ingredients
from c in i.ToCharArray()
select c;

foreach (var item in query2)
{
   Console.WriteLine(item);
}

عملگرهای جداکننده (Partitioning Operators)
عملگر‌های جداکننده، یک توالی ورودی را دریافت و آنها را از هم جدا می‌کنند.

Take
عملگر Takeیک توالی ورودی را دریافت کرده و تعداد مشخصی از توالی را باز می‌گرداند.
مثال: عملگر Take، سه عضو اول توالی Ingredient را باز می‌گرداند:
 Ingredient[] ingredients =
{
   new Ingredient{Name = "Sugar", Calories=500},
   new Ingredient{Name = "Egg", Calories=100},
   new Ingredient{Name = "Milk", Calories=150},
   new Ingredient{Name = "Flour", Calories=50},
   new Ingredient{Name = "Butter", Calories=200},
};

IEnumerable<Ingredient> query = ingredients.Take(3);
foreach (var ingredient in query)
{
   Console.WriteLine(ingredient.Name);
}
خروجی کد بالا :
 Sugar
Egg
Milk
همچون سایر عملگر‌های پرس و جو، عملگر Take هم می‌تواند بصورت زنجیروار استفاده شود. در مثال زیر ابتدا عملگر Where برای محدود کردن عناصر با شرطی خاص و سپس عملگر Take برای جدا کردن عناصر حاصل از نتیجه‌ی مرحله قبل مورد استفاده قرار گرفته است:
Ingredient[] ingredients =
{
   new Ingredient{Name = "Sugar", Calories=500},
   new Ingredient{Name = "Egg", Calories=100},
   new Ingredient{Name = "Milk", Calories=150},
   new Ingredient{Name = "Flour", Calories=50},
   new Ingredient{Name = "Butter", Calories=200},
};

IEnumerable<Ingredient> query = ingredients.Where(x=>x.Calories>100).Take(2);
foreach (var ingredient in query)
{
   Console.WriteLine(ingredient.Name);
}
خروجی کد بالا :
Sugar
Milk

پیاده سازی توسط عبارت‌های پرس و جو

کلمه‌ی کلیدی (Key word) جایگزینی برای عملگر Take وجود ندارد، ولی می‌توان با ترکیب دو روش نوشتن پرس و جو، خروجی مورد نظر را تولید کرد:
 IEnumerable<Ingredient> query =
(from i in ingredients
  where i.Calories > 100
  select i).Take(2);
TakeWhile
عملگر TakeWhile بر عکس عملگر Take تعداد مشخصی را باز می‌گرداند . این عملگر تا زمانی که گزاره با عناصر مطابقت داشته باشد، اجرا می‌شود و در غیر اینصورت خاتمه پیدا می‌کند.
کد زیر تا زمانی که خصوصیت Calorie توالی ورودی بزرگتر و مساوی 100 باشد، عناصر را جدا می‌کند.
Ingredient[] ingredients =
{
   new Ingredient{Name = "Sugar", Calories=500},
   new Ingredient{Name = "Egg", Calories=100},
   new Ingredient{Name = "Milk", Calories=150},
   new Ingredient{Name = "Flour", Calories=50},
   new Ingredient{Name = "Butter", Calories=200},
};

IEnumerable<Ingredient> query = ingredients.TakeWhile(x => x.Calories >= 100);
foreach (var ingredient in query)
{
   Console.WriteLine(ingredient.Name);
}
خروجی کد بالا :
 Sugar
Egg
Milk
همانطور که مشاهده می‌کنید، وقتی عملگر TakeWhile به عنصری می‌رسد که گزاره‌ی آن را نقض می‌کند، متوقف می‌شود (در اینجا Flour). در حالی که ممکن است عناصری بعد از Flour وجود داشته باشند که با گزاره‌ی TakeWhile تطابق داشته باشند.

پیاده سازی توسط عبارت‌های پرس و جو
برای این عملگر هم کلمه‌ی کلیدی (Key word) جایگزینی وجود ندارد و با ترکیب دو روش نوشتن پرس و جو نتیجه‌ی دلخواه حاصل می‌شود.
 
Skip
این عملگر تعداد مشخصی از عناصر را از ابتدای توالی نادیده گرفته و باقی عناصر را باز می‌گرداند.
کد زیر سه عضو اول توالی را نادیده گرفته و مابقی را باز می‌گرداند:
Ingredient[] ingredients =
{
   new Ingredient{Name = "Sugar", Calories=500},
   new Ingredient{Name = "Egg", Calories=100},
   new Ingredient{Name = "Milk", Calories=150},
   new Ingredient{Name = "Flour", Calories=50},
   new Ingredient{Name = "Butter", Calories=200},
};

IEnumerable<Ingredient> query = ingredients.Skip(3);
foreach (var ingredient in query)
{
   Console.WriteLine(ingredient.Name);
}
خروجی کد بالا :
 Flour
Butter

پیاده سازی توسط عبارت‌های پرس و جو

برای این عملگر هم کلمه‌ی کلیدی (Key word) جایگزینی وجود ندارد و با ترکیب دو روش نوشتن پرس و جو، نتیجه‌ی دلخواه حاصل می‌شود.
با ترکیب عملگر Take و Skip می‌توان اطلاعات را به‌صورت صفحه بندی به کاربر ارائه کرد. مثال زیر این حالت را نشان می‌دهد.
IEnumerable<Ingredient> firstPage = ingredients.Take(2);
IEnumerable<Ingredient> secondPage = ingredients.Skip(2).Take(2);
IEnumerable<Ingredient> thirdPage = ingredients.Skip(4).Take(2);

Console.WriteLine("First Page : ");
foreach (var ingredient in firstPage)
{
   Console.WriteLine(" - " + ingredient.Name);
}

Console.WriteLine("Second Page : ");
foreach (var ingredient in secondPage)
{
   Console.WriteLine(" - " + ingredient.Name);
}

Console.WriteLine("Third Page : ");
foreach (var ingredient in thirdPage)
{
   Console.WriteLine(" - " + ingredient.Name);
}
خروجی کد بالا :
 First Page :
 - Sugar
 - Egg
Second Page :
 - Milk
 - Flour
Third Page :
 - Butter
SkipWhile
عملگر SkipWhile، مثل عملگر TakeWhile، از یک گزاره برای ارزیابی عناصر توالی استفاده می‌کند. این عملگر تا زمانیکه عناصر توالی، گزاره را نقض نکنند، عناصر را نادیده می‌گیرد.

مثال:
Ingredient[] ingredients =
{
   new Ingredient{Name = "Sugar", Calories=500},
   new Ingredient{Name = "Egg", Calories=100},
   new Ingredient{Name = "Milk", Calories=150},
   new Ingredient{Name = "Flour", Calories=50},
   new Ingredient{Name = "Butter", Calories=200},
};

IEnumerable<Ingredient> query = ingredients.SkipWhile(x => x.Name != "Milk");
foreach (var ingredient in query)
{
   Console.WriteLine(ingredient.Name);
}
خروجی کد بالا:
 Milk
Flour
Butter
اشتراک‌ها
دوره 8 ساعته Microservices در دات نت

Introduction to .NET Microservices (.NET 8)

In this Introduction course, we will learn Microservices with .NET 8 (MVC).
Microservices is an upcoming technology, where it is very easy to scale and break down large project in simple and manageable services.
In this course we will build multiple services and see how they function together by communicating in synchronous and asynchronous manner.

⭐️ Course Contents ⭐️
⌨️ (0:00:01) Section 1 -  Welcome & Getting Started
⌨️ (0:28:15) Section 2 -  Coupon API - Fundamentals
⌨️ (1:15:54) Section 3 -  Coupon API - CRUD
⌨️ (2:21:24) Section 4 -  Auth API
⌨️ (3:20:08) Section 5 -  Consuming Auth API
⌨️ (4:26:53) Section 6 - Product API
⌨️ (4:57:59) Section 7 - Home and Details Page
⌨️ (5:09:35) Section 8 - Shopping Cart
⌨️ (6:08:04) Section 9 - Shopping Cart in Web Project
⌨️ (6:58:06) Section 10 - Service Bus
⌨️ (7:23:42) Section 11 - Email API - Service Bus
⌨️ (7:54:11) What's Next? 

دوره 8 ساعته Microservices در دات نت
نظرات مطالب
مروری بر کاربردهای Action و Func - قسمت دوم
سلام میشه یه توضیحی درباره کد زیر بدید؟
    public static T CacheRead<T>(this HttpContextBase httpContext, string key, int durationMinutes, Func<T> ifNullRetrievalMethod)
        {
            var item = httpContext.Cache[key];
            if (item == null)
            {
                item = ifNullRetrievalMethod();
                if (item == null)
                    return default(T);
 
                CacheInsert(httpContext, key, item, durationMinutes);
            }
            return (T)item;
        }
نظرات مطالب
تعریف نوع جنریک به صورت متغیر
بله ببخشید چون پست بلافاصله نمایش پیدا نمیکنه متوجه نشدم که بهم ریخته.
در این آدرس کد رو قرار دادم : http://pastebin.com/Q4bu1VV1
ولی از این خط 14 ارور میگیرم. در کل میخواستم بدونم چطور T رو به هر کلاسی Cast کنم. ممنون
نظرات مطالب
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 2#
با سلام

از مطلب مفیدی که تهیه کردید ممنون.
می‌شود از طریق خاصیت Brush که فعلا فقط خواندنی هست، طرح‌های مختلفی برای پس زمینه اشیاع ایجاد کرد. مانند Paint.net و یا MS Paint.

اگر به صورت زیر تعریف کنیم فکر می‌کنم کمی کامل‌تر باشه!

        private Brush _backgroundBrush;

        /// <summary>
        /// Gets or sets the brush.
        /// </summary>
        /// <value>
        /// The brush.
        /// </value>
        public Brush BackgroundBrush
        {
            get
            {
                return _backgroundBrush;
            }
            private set
            {
                _backgroundBrush = (value != null) ? value : new SolidBrush(BackgroundColor);
            }
        }
        //-------------------------------------[Methode for set brush]--------------------------------------
        public virtual void SetBackgroundBrushAsHatch(HatchStyle hatchStyle)
        {
            HatchBrush brush = new HatchBrush(hatchStyle, BackgroundColor);
            BackgroundBrush = brush;
        }

        public virtual void SetBackgroundBrushAsSolid()
        {
            SolidBrush brush = new SolidBrush(BackgroundColor);
            BackgroundBrush = brush;
        }

        public virtual void SetBackgroundBrushAsLinearGradient()
        {
            LinearGradientBrush brush = new LinearGradientBrush(StartPoint, EndPoint, ForeColor, BackgroundColor);
            BackgroundBrush = brush;
        }

که اگر بخواهیم میتونیم باز بیشتر Customize بکنیمشون.
مطالب
بررسی ابزار SQL Server Profiler

مقدمه

Profiler یک ابزار گرافیکی برای ردیابی و نظارت بر کارآئی SQL Server است. امکان ردیابی اطلاعاتی در خصوص رویدادهای مختلف و ثبت این داده‌ها در یک فایل (با پسوند trc) یا جدول برای تحلیل‌های آتی نیز وجود دارد. برای اجرای این ابزار مراحل زیر را انجام دهید:

Start > Programs> Microsoft SQL Server > Performance Tools> SQL Server Profiler
و یا در محیط  Management Studio از منوی Tools گزینه SQL Server Profiler را انتخاب نمائید.


1- اصطلاحات

1-1- رویداد (Event):

یک رویداد، کاری است که توسط موتور بانک اطلاعاتی (Database Engine) انجام می‌شود. برای مثال هر یک از موارد زیر یک رویداد هستند.
-  متصل شدن کاربران (login connections) قطع شدن ارتباط یک login
-  اجرای دستورات T-SQL، شروع و پایان اجرای یک رویه، شروع و پایان یک دستور در طول اجرای یک رویه، اجرای رویه‌های دور Remote Procedure Call
-  باز شدن یک Cursor
-  بررسی و کنترل مجوزهای امنیتی

1-2- کلاس رویداد (Event Class):

برای بکارگیری رویدادها در Profiler، از یک Event Class استفاده می‌کنیم. یک Event Class رویدادی است که قابلیت ردیابی دارد. برای مثال بررسی ورود و اتصال کاربران با استفاده از کلاس Audit Login قابل پیاده سازی است. هر یک از موارد زیر یک Event Class هستند.
-  SQL:BatchCompleted
-  Audit Login
-  Audit Logout
-  Lock: Acquired
-  Lock: Released

1-3- گروه رویداد (Event Category):

یک گروه رویداد شامل رویدادهایی است که به صورت مفهومی دسته بندی شده اند. برای مثال، کلیه رویدادهای مربوط به قفل‌ها از جمله Lock: Acquired (بدست آوردن قفل) و Lock: Released (رها کردن قفل) در گروه رویداد Locks قرار  دارند.

1-4- ستون داده ای (Data Column):

یک ستون داده ای، خصوصیت و جزئیات یک رویداد را شامل می‌شود. برای مثال در یک Trace که رویدادهای Lock: Acquired را نظارت می‌کند، ستون Binary Data شامل شناسه (ID) یک صفحه و یا یک سطر قفل شده است و یا اینکه ستون Duration مدت زمان اجرای یک رویه را نمایش می‌دهد.

1-5- الگو (Template):

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

1-6- ردیاب (Trace):

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

1-7- فیلتر (Filter):

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


2- انتخاب الگو (Profiler Trace Templates)

از آنجائیکه اصولاً انتخاب Eventهای مناسب، کار سخت و تخصصی می‌باشد برای راحتی کار تعدادی Template‌های آماده وجود دارد، برای مثال TSQL_Duration تاکیدش روی مدت انجام کار است و یا SP_Counts در مواردی که بخواهیم رویه‌های ذخیره شده را بهینه کنیم استفاده می‌شود در جدول زیر به شرح هر یک پرداخته شده است:
 الگو  هدف 
 Blank   ایجاد یک Trace کلی 
 SP_Counts   ثبت اجرای هر رویه ذخیره شده برای تشخیص اینکه هر رویه چند بار اجرا شده است 
 Standard   ثبت آمارهای کارائی برای هر رویه ذخیره شده و Query‌های عادی SQL که اجرا می‌شوند و عملیات ورود و خروج هر Login (پیش فرض) 
 TSQL   ثبت یک لیست از همه رویه‌های ذخیره شده و Query‌های عادی SQL که اجرا می‌شوند ولی آمارهای کارائی را شامل نمی‌شود 
 TSQL_Duration   ثبت مدت زمان اجرای هر رویه ذخیره شده و هر Query عادی SQL 
 TSQL_Grouped   ثبت تمام  login‌ها و logout‌ها در طول اجرای رویه‌های ذخیره شده و هر Query عادی SQL، شامل اطلاعاتی برای شناسائی برنامه و کاربری که درخواست را اجرا می‌کند 
 TSQL_Locks   ثبت اطلاعات انسداد (blocking) و بن بست (deadlock) از قبیل blocked processes، deadlock chains، deadlock graphs,... . این الگو همچنین درخواست‌های تمام رویه‌های ذخیره شده و تمامی دستورات هر رویه و  هر Query عادی SQL را دریافت می‌کند 
 TSQL_Replay   ثبت اجرای رویه‌های ذخیره شده و Query‌های SQL در یک SQL Instance و  مهیا کردن امکان اجرای دوباره عملیات در سیستمی دیگر 
 TSQL_SPs   ثبت کارائی برای Query‌های SQL، رویه‌های ذخیره شده و تمامی دستورات درون یک رویه ذخیره شده و نیز عملیات ورود و خروج هر Login 
 Tuning   ثبت اطلاعات کارائی برای Query‌های عادی SQL و رویه‌های ذخیره شده و یا تمامی دستورات درون یک رویه ذخیره شده 

3- انتخاب رویداد (SQL Trace Event Groups)

رویداد‌ها در 21 گروه رویداد دسته بندی می‌شوند که در جدول زیر لیست شده اند:
 گروه رویداد  هدف 
 Broker  13 رویداد برای واسطه سرویس (Service Broker) 
 CLR   1 رویداد برای بارگذاری اسمبلی‌های CLR (Common Language Runtime) 
 Cursors   7 رویداد برای ایجاد، دستیابی و در اختیار گرفتن Cursor 
 Database   6 رویداد برای رشد/کاهش  (grow/shrink) فایل های  Data/Log همچنین تغییرات حالت انعکاس (Mirroring) 
 Deprecation   2 رویداد برای آگاه کردن وضعیت نابسامان درون یک SQL Instance 
 Errors and
Warnings 
 16 رویداد برای خطاها، هشدارها و پیغام‌های اطلاعاتی که ثبت شده است 
 Full Text   3  رویداد برای پیگیری یک شاخص متنی کامل 
 Locks   9 رویداد برای بدست آوردن، رها کردن قفل و بن بست (Deadlock) 
 OLEDB   5 رویداد برای درخواست‌های توزیع شده و RPC (اجرای رویه‌های دور) 
 Objects   3 رویداد برای وقتی که یک شی ایجاد، تغییر یا حذف می‌شود 
 Performance   14 رویداد برای ثبت نقشه درخواست‌ها (Query Plan) برای استفاده نقشه راهنما (Plan Guide) به منظور بهینه سازی کارائی درخواست ها،  همچنین این گروه رویداد در خواست‌های متنی کامل (full text) را ثبت می‌کند 
 Progress Report   10 رویداد برای ایجاد Online Index 
 Query
Notifications 
 4 رویداد برای سرویس اطلاع رسان (Notification Service) 
 Scans   2 رویداد برای وقتی که یک جدول یا شاخص، پویش می‌شود 
 Security Audit   44 رویداد برای وقتی که مجوزی استفاده شود، جابجائی هویتی رخ دهد، تنظیمات امنیتی اشیائی تغییر کند،یک  SQL Instance  شروع و متوقف شود و یک  Database جایگزین شود یا از آن پشتیبان گرفته شود 
 Server  3 رویداد برای Mount Tape، تغییر کردن حافظه سرور و بستن یک فایل Trace 
 Sessions   3 رویداد برای وقتی که Connection‌ها موجود هستند و یک Trace فعال می‌شود، همچنین یک Trigger  و یک تابع دسته بندی(classification functions) مربوط به مدیریت منابع(resource governor) رخ دهد 
 Stored Procedures   12 رویداد برای اجرای یک رویه ذخیره شده و دستورات درون آن ، کامپایل مجدد و استفاده از حافظه نهانی (Cache) 
 Transactions   13 رویداد برای شروع، ذخیره ، تائید و لغو یک تراکنش 
 TSQL   9  رویداد برای اجرای Query‌های SQL و جستجوهای XQUERY (در داده‌های XML)  
 User Configurable   10 رویداد که شما می‌توانید پیکربندی کنید 
به طور معمول بیشتر از گروه رویدادهای Locks، Performance، Security Audit، Stored Procedures و TSQL استفاده می‌شود.


4- انتخاب ستون‌های داده ای ( Data Columns)

اگرچه می‌توان همه‌ی 64 ستون داده ای ممکن را برای ردیابی انتخاب کرد ولیکن داده‌های Trace شما زمانی مفید خواهند بود که اطلاعات ضروری را ثبت کرده باشید. برای مثال شماره ترتیب تراکنش‌ها را،  برای یک رویداد RPC:Completed می‌توانید برگردانید، اما همه رویه‌های ذخیره شده مقادیر را تغییر نمی‌دهند بنابراین شماره ترتیب تراکنش‌ها فضای بیهوده ای را مصرف می‌کند. بعلاوه همه ستون‌های داده ای برای تمامی رویداد‌های Trace معتبر نیستند. برای مثال Read ، Write ،CPU و Duration برای رویداد‌های RPC:Starting و SQL:BatchStarting معتبر نیستند.
ApplicationName، NTUserName، LoginName، ClientProcessID، SPID، HostName، LoginSID، NTDomainName و SessionLoginName ، مشخص می‌کنند چه کسی و از چه منشاء دستور را اجرا کرده است.
ستون SessionLoginName معمولاً نام Login ای که از آن برای متصل شدن به SQL Instance استفاده شده است را نشان می‌دهد. در حالیکه ستون LoginName نام کاربری را که دستور را اجرا می‌کند نشان می‌دهد (EXECUTE AS). ستون ApplicationName خالی است مگر اینکه در ConnectionString برنامه کاربردیمان این خصوصیت (Property) مقداردهی شده باشد. ستون StartTime و EndTime زمان سرحدی برای هر رویداد را ثبت می‌کند این ستون‌ها بویژه در هنگامی که به عملیات Correlate  نیاز دارید مفید هستند.


5- بررسی چند سناریو نمونه

•  یافتن درخواست هائی (Queries) که بدترین کارایی را دارا هستند.

برای ردیابی درخواست‌های ناکارا، از رویداد RPC:Completed از دسته Stored Procedure و رویداد SQL:BatchCompleted از دسته TSQL استفاده می‌شود.

•  نظارت بر کارایی رویه ها

برای ردیابی کارائی رویه ها، از رویدادهای SP:Starting، SP:Completed، SP:StmtCompleted و SP:StmtStaring از کلاس Stored Procedure و رویدادهای SQL:BatchStarting ، SQL:BatchCompleted از کلاس TSQL استفاده می‌شود.

•  نظارت بر اجرای دستورات T-SQL توسط هر کاربر

برای ردیابی دستوراتی که توسط یک کاربر خاص اجرا می‌شود، نیاز به ایجاد یک Trace برای نظارت بر رویدادهای کلاس‌های Sessions، ExistingConnection و TSQL داریم همچنین لازم است نام کاربر در قسمت فیلتر  و با استفاده از DBUserName مشخص شود.

•  اجرا دوباره ردیاب (Trace Replay)

این الگو  معمولاً برای debugging استفاده می‌شود برای این منظور  از الگوی Replay استفاده می‌شود. در ضمن امکان اجرای دوباره عملیات در سیستمی دیگر با استفاده از این الگو مهیا می‌شود.

•  ابزار Tuning Advisor (راهنمای تنظیم کارائی)

این ابزاری برای تحلیل کارائی یک یا چند بانک اطلاعاتی و تاثیر عملکرد آنها بر بار کاری (Workload) سرویس دهنده است. یک بار کاری مجموعه ای از دستورات T-SQL است که روی بانک اطلاعاتی اجرا می‌شود. بعد از تحلیل تاثیر بارکاری بر بانک اطلاعاتی، Tuning Advisor توصیه هائی برای اضافه کردن، حذف و یا تغییر طراحی فیزیکی ساختار بانک اطلاعاتی ارائه می‌دهد این تغییرات ساختاری شامل پیشنهاد برای تغییر ساختاری موارد Clustered Indexes، Nonclustered Indexes، Indexed View و Partitioning است.
برای ایجاد بارکاری می‌توان از یک ردیاب تهیه شده در SQL Profiler استفاده کرد برای این منظور از الگوی Tuning استفاده می‌شود و یا رویدادهای RPC:Completed، SQL:BatchCompleted و SP:StmtCompleted را ردیابی نمائید.

•  ترکیب ابزارهای نظارتی (Correlating Performance and Monitoring Data)

یک Trace برای ثبت اطلاعاتی که در یک SQL Instance رخ می‌دهد، استفاده می‌شود. System Monitor  برای ثبت شمارنده‌های کارائی(performance counters) استفاده می‌شود و همچنین از منابع سخت افزاری و اجزای دیگر که روی سرور اجرا می‌شوند، تصاویری فراهم می‌کند. توجه شود که در مورد  Correlating یک فایل ردیاب (trace file) و یک Counter Log (ابزار Performance )، ستون داده ای StartTime و EndTime باید انتخاب شود، برای این کار از منوی File گزینه Import Performance Data انتخاب می‌شود.

•  جستجوی علت رخ دادن یک بن بست

برای ردیابی علت رخ دادن یک بن بست، از رویدادهای RPC:Starting، SQLBatchStarting از دسته Stored Procedure و رویدادهای Deadlock graph، Lock:Deadlock و Lock:Deadlock Chain از دسته Locks استفاده می‌شود. ( در صورتی که نیاز به یک ارائه گرافیکی دارید از  Deadlock graph استفاده نمائید، خروجی مطابق تصویر زیر می‌شود).


5-1- ایجاد یک Trace

1-  Profiler را اجرا کنید از منوی File گزینه New Trace را انتخاب کنید و به SQL Instance مورد نظرتان متصل شوید.
2-  مطابق تصویر زیر برای Trace یک نام و الگو و تنظیمات ذخیره سازی فایل را مشخص کنید.


3-  بر روی قسمت Events Selection کلیک نمائید.
4-  مطابق تصویر زیر رویداد‌ها و کلاس رویداد‌ها را انتخاب کنید، ستون‌های TextData، NTUserName، LoginName، CPU،Reads،Writes، Duration، SPID، StartTime، EndTime، BinaryData، DataBaseName، ServerName و ObjectName را انتخاب کنید.

5-  روی Column Filters کلیک کنید و مطابق تصویر زیر برای DatabaseName فیلتری تنظیم کنید.


6-  روی Run کلیک کنید. تعدادی Query و رویه ذخیره شده مرتبط با پایگاه داده AdventureWorks اجرا کنید .


5-2- ایجاد یک Counter Log

برای ایجاد یک Counter Log  مراحل زیر  را انجام دهید:
1-  ابزار Performance را اجرا کنید (برای این کار عبارتPerfMon را در قسمت Run بنویسید).
2-  در قسمت Counter Logs یک log ایجاد کنید.
3-  روی Add Counters کلیک کرده و مطابق تصویر موارد زیر را انتخاب کنید.
Select counters from list 
Performance Object 
 Output Queue Length  Network Interface 
 % Processor Time  Processor 
 Processor Queue Length  System 
 Buffer Manager:Page life expectancy  SQLServer 
 
4-  روی Ok کلیک کنید تا Counter Log ذخیره شود سپس روی آن راست کلیک کرده و آنرا Start کنید.


5-3- ترکیب ابزارهای نظارتی (Correlating SQL Trace and System Monitor Data)

1-  Profiler را اجرا کنید از منوی File گزینه Open و سپس Trace File را انتخاب کنید فایل trc را که در گام اول ایجاد کردید، باز نمائید.
2-  از منوی File گزینه Import Performance Data را انتخاب کنید و فایل counter log  را که در مرحله قبل ایجاد کردید  انتخاب کنید.



نکته: اطلاعات فایل trc را می‌توان درون یک جدول وارد کرد، بدین ترتیب می‌توان آنالیز بیشتری داشت به عنوان مثال دستورات زیر این عمل را انجام می‌دهند.


 SELECT * INTO dbo.BaselineTrace
FROM fn_trace_gettable(' c:\performance baseline.trc ', default);
با اجرای دستور زیر جدولی با نام  BaselineTrace ایجاد و محتویات Trace مان (performance baseline.trc) در آن درج می‌گردد.
 
مطالب
خواندن اطلاعات API فیدبرنر

مطلبی را در سایت رادیکال 2 در مورد نمایش تعداد خواننده یک فید دیدم که پیاده سازی آن با سی شارپ و xml serialization به صورت زیر است:

using System;
using System.Xml;
using System.Xml.Serialization;

namespace Test
{
/// <summary>
/// کلاسی جهت نمایش تعداد خواننده فید وبلاگ شما
/// <example>CFeedBurner data = new CFeedBurner { FeedID = "fhphjt61bueu08k93ehujpu234" };
/// MessageBox.Show(data.Circulation().ToString());</example>
/// </summary>
class CFeedBurner
{
/// <summary>
/// آی دی فید شما زمانیکه به فید برنر لاگین کرده‌اید در تایتل صفحه مربوطه
/// </summary>
public string FeedID { get; set; }

/// <summary>
/// نگاشت فید به یک کلاس
/// </summary>
/// <returns>کلاس متناظر با فید</returns>
/// <exception cref="Exception">لطفا شماره شناسایی فید را وارد کنید</exception>
rsp deserializeFromXML()
{
if (FeedID == null)
throw new Exception("لطفا شماره شناسایی فید را وارد کنید");

XmlSerializer deserializer =
new XmlSerializer(typeof(rsp));
using (XmlReader reader = XmlReader.Create(
string.Format("https://feedburner.google.com/api/awareness/1.0/GetFeedData?id={0}", FeedID)))
{
return (rsp)deserializer.Deserialize(reader);
}
}

/// <summary>
/// دریافت تعداد خواننده فید
/// </summary>
/// <returns>آمار فید</returns>
/// <exception cref="Exception">اطلاعات فید شما قابل دریافت نیست</exception>
public int Circulation()
{
rsp data = deserializeFromXML();
if (data == null || data.feed == null || data.feed.Length == 0)
throw new Exception("اطلاعات فید شما قابل دریافت نیست");

if (data.feed[0].entry == null || data.feed[0].entry.Length == 0)
throw new Exception("اطلاعات فید شما قابل پردازش نیست");

return int.Parse(data.feed[0].entry[0].circulation);
}
}
}

کلاس rsp از فایل xml فید استاندارد سایت فیدبرنر درست شده است. روش تولید آن‌را قبلا توضیح داده بودم. به سادگی اجرای دو سطر زیر است:

xsd.exe GetFeedData.xml
xsd.exe GetFeedData.xsd /c

دریافت فایل‌های کلاس‌های نامبرده شده.

اشتراک‌ها
بررسی روش‌های صحیح استفاده‌ی از Async/Await

[09:65] - Refactoring async operations with commands
[12:52] - Don't use .Wait()
[15:41] - Avoiding context switches with ConfigureAwait(false)
[19:45] - Sometimes you don't need to use async / await
[21:22] - Using async / await inside of try/catch and using statement blocks 

بررسی روش‌های صحیح استفاده‌ی از Async/Await
نظرات مطالب
بررسی اینترفیس ICommand در WPF
برای عمومی‌تر کردن پیاده سازی ICommand یک چنین کلاسی را می‌توان تدارک دید:
using System;
using System.Windows.Input;

namespace Common.Mvvm
{
    public class DelegateCommand<T> : ICommand
    {
        readonly Func<T, bool> _canExecute;
        readonly Action<T> _executeAction;

        public DelegateCommand(Action<T> executeAction, Func<T, bool> canExecute = null)
        {
            if (executeAction == null)
                throw new ArgumentNullException("executeAction");

            _executeAction = executeAction;
            _canExecute = canExecute;
        }

        public event EventHandler CanExecuteChanged
        {
            add { if (_canExecute != null) CommandManager.RequerySuggested += value; }
            remove { if (_canExecute != null) CommandManager.RequerySuggested -= value; }
        }

        public bool CanExecute(object parameter)
        {
            return _canExecute == null || _canExecute((T)parameter);
        }

        public void Execute(object parameter)
        {
            _executeAction((T)parameter);
        }
    }
}
و بعد برای استفاده‌ی از آن، به صورت یک خاصیت عمومی در سطح ViewModel تعریف می‌شود:
public DelegateCommand<object> DoCopyAllLines { set; get; }
سپس وهله سازی آن در سازنده‌ی کلاس:
DoCopyAllLines = new DelegateCommand<object>(CopyAllLines, info => true);
و بعد برای پیاده سازی متد execute آن:
private void CopyAllLines(object data)
{
   // ...
}