نظرات مطالب
رمزگذاری رویه‌های ذخیره شده در SQL Server
سلام
مرسی از مقاله شما، فقط نکته ای در مورد Stored Procedure‌های Encrypt شده وجود دارد، و آن این است که، این نوع Procedure‌ها را نمی‌توان بطور قابل فهم در Execution Plan مشاهده نمود.
مثال:
CREATE PROCEDURE #RegularSP
AS
SELECT TOP 10 City
FROM Person.Address
GO
اجرا با Execution Plan
EXEC #RegularSP
خروجی بصورت زیر خواهد بود:

ایجاد Stored Procedure بصورت Encrypt شده:
CREATE PROCEDURE #EncryptSP
WITH ENCRYPTION
AS
SELECT TOP 10 City
FROM Person.Address
اجرا با Execution Plan 
EXEC #EncryptSP
خروجی بصورت زیر خواهد بود: 

حذف Stored Procedure‌های ایجاد شده:
DROP PROCEDURE #RegularSP
DROP PROCEDURE #EncryptSP
 
مطالب
WF:Windows Workflow #۵
در این قسمت به پیاده سازی یک فرآیند سفارش ساده می‌پردازیم. ابتدا یک پروژه از نوع Workflow Console Application را ایجاد کرده و نام آن را Order Process می‌گذاریم و سپس کلاس‌های زیر را به آن اضافه می‌کنیم:
public class OrderItem
    {
        public int OrderItemID { get; set; }
        public int Quantity { get; set; }
        public string ItemCode { get; set; }
        public string Description { get; set; }
    }

    public class Order
    {
        public Order()
        {
            Items = new List<OrderItem>();
        }
        public int OrderID { get; set; }        
        public string Description { get; set; }         
        public decimal TotalWeight { get; set; }         
        public string ShippingMethod { get; set; }
        public List<OrderItem> Items { get; set; } 
    }
در اینجا دوکلاس تعریف شده است؛ یکی به نام OrderItem می‌باشد که شامل اطلاعات مربوط به میزان سفارش بوده و دیگری کلاس Order می‌باشد که شامل مشخصات سفارش است. سپس فایل OrderWF.xaml را باز کرده و شروع به ساخت فرآیند مورد نظر می‌کنیم. ابتدا یک Sequence را به درون صفحه کشیده و پس از آن در قسمت Arguments دو متغییر را تعریف می‌کنیم. یکی به نام TotalAmount و از نوع Decimal و Out می‌باشد و دیگری به نام OrderInfo که از نوع کلاس Order و In می‌باشد. سپس  یک کنترل WriteLine را به آن اضافه می‌کنیم و در خاصیت Text آن رشته "Order Received" را قرار می‌دهیم. در ادامه یک کنترل Assign را در زیر آن قرار داده و مقدار متغییر TotalAmount را مساوی صفر وارد می‌کنیم.

نکته : برای اینکه نوع متغییر OrderInfo را از نوع کلاس Order قرار دهیم٬ ابتدا DropDown مربوطه را انتخاب کرده و گزینه Browse For Type را انتخاب می‌کنیم تا پنجره مورد نظر باز شود و از طریق آن، کلاس مورد نظر را انتخاب می‌کنیم. اگر در این قسمت کلاس مورد نظر یافت نشد، نیاز است ابتدا عمل Build Project را یک بار انجام دهیم.

 بعضی از کنترل‌های Workflow در قسمت Toolbox موجود نمی‌باشند. از جمله این کنترل‌ها می‌توان به کنترل Add اشاره کرد. برای استفاده از این کنترل، ابتدا باید آن را به لیست کنترل‌ها اضافه نمود. جهت این امر٬ ابتدا در قسمت Toolbox یک Tab جدید را با نام دلخواه ایجاد کرده و سپس بر روی Tab کلیک راست نموده و گزینه Choose Items را انتخاب می‌کنیم. سپس از قسمت System.Activities.Components کنترل Add را انتخاب کرده و سپس بر روی دکمه OK کلیک می‌نمائیم. حال کنترل Add به لیست کنترل‌ها در Tab مورد نظر اضافه شده است.
در ادامه یک کنترل Switch را به فرایند خود اضافه کرده و مقدار T آن را برابر String قرار می‌دهیم؛ زیرا نوع داده‌ای که در قسمت Expression کنترل Switch قرار می‌گیرد، از نوع رشته می‌باشد. پس از اضافه کردن کنترل مورد نظر، کد زیر را به قسمت Expression کنترل اضافه خواهیم کرد:
OrderInfo.ShippingMethod
سپس در کنترل Switch، بر روی قسمت Add new case کلیک کرده و رشته‌های مورد نظر را اضافه می‌کنیم که شامل  "" NextDay"" و  ""2ndDay"" می‌باشند. اکنون در بدنه هر دو Case، کنترل Add را اضافه می‌کنیم. در هنگام اضافه کردن باید برای سه خصوصیت، نوع مشخص شود و نوع هر سه را برابر Decimal قرار می‌دهیم.
در ادامه کنترل Add را انتخاب کرده و به خاصیت Right آنها به ترتیب مقدار های 10.0m و 15.0m را اضافه می‌کنیم و برای خصوصیت Result هر دو کنترل، متغیر TotalAmount را انتخاب می‌کنیم. سپس یک کنترل Assign را به صفحه اضافه کرده و در قسمت To، متغییر  TotalAmount را قرار می‌دهیم و در قسمت Value کد زیر را:
TotalAmount + (OrderInfo.TotalWeight * 0.50m) 
و در آخر با ستفاده از کنترل WriteLine به چاپ محتوای متغییر TotalAmount می‌پر‌دازیم.

اکنون برای اینکه بتوانیم برنامه را اجرا کنیم، کد زیر را به کلاس Program.cs اضافه می‌کنیم:
static void Main(string[] args)
        {
            Order myOrder = new Order
            {
                OrderID = 1,
                Description = "Need some stuff",
                ShippingMethod = "2ndDay",
                TotalWeight = 100
            };
            IDictionary<String, object> input = new Dictionary<String, Object>
            {
                { "OrderInfo",myOrder}
            };
            IDictionary<String, Object> output = WorkflowInvoker.Invoke(new OrderWF(), input);
            Decimal total = (Decimal)output["TotalAmount"];
            Console.WriteLine("Workflow returned ${0} for my order total", total);
            Console.WriteLine("Press ENTER to exit"); 
            Console.ReadLine();

            //Activity workflow1 = new OrderWF();
            //WorkflowInvoker.Invoke(workflow1);
        }
در اینجا علت استفاده از IDictionary، نوع خروجی متد Invoke می‌باشد. در ادامه به کامل کردن این مثال پرداخته می‌شود.
نظرات مطالب
Blazor 5x - قسمت 30 - برنامه‌ی Blazor WASM - افزودن پرداخت آنلاین توسط درگاه مجازی پرباد
سلام
موقع ریدایرکت از api به سمت کلاینت پس از پرداخت خطای CORS  داریم . علت چیه ؟ با اینکه اگر api را دستی اجرا کنیم بدون مشکل ریدایرکت میشه ، 
basket:1 Access to fetch at ' https://localhost:7145  ' (redirected from 'https://localhost:44307/api/v1.0/order/pay/44') from origin 'https://localhost:7145' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
مطالب دوره‌ها
بررسی مقدماتی مراحل کامپایل یک قطعه کد سی‌شارپ و آشنایی با OpCodes
کامپایلر سی‌شارپ چگونه عمل می‌کند؟

کار یک کامپایلر ترجمه قطعه‌ای از اطلاعات به چیز دیگری است. کامپایلر سی‌شارپ، machine code معادل دستورات دات نتی را تهیه نمی‌کند. Machine code، کدی است که مستقیما بر روی CPU قابل اجرا است. در دات نت این مرحله به CLR یا Common language runtime واگذار شده است تا کار اجرای نهایی کدهای تهیه شده توسط کامپایلر سی‌شارپ را انجام دهد.
بنابراین زمانیکه در VS.NET سعی در اجرای یک قطعه کد می‌نمائیم، مراحل ذیل رخ می‌دهند:
الف) فایل‌های سی‌شارپ پروژه، توسط کامپایلر بارگذاری می‌شوند.
ب) کامپایلر کدهای این فایل‌ها را پردازش می‌کند.
ج) سپس چیزی را به نام MSIL تولید می‌کند.
د) در ادامه فایل خروجی نهایی، با افزودن PE Headers تولید می‌شود. توسط PE headers مشخص می‌شود که فایل تولیدی نهایی آیا اجرایی است، یا یک DLL می‌باشد و امثال آن.
ه) و در آخر، فایل اجرایی تولیدی توسط CLR بارگذاری و اجرا می‌شود.


MSIL چیست؟

MSIL مخفف Microsoft intermediate language است. به آن CIL یا Common intermediate language هم گفته می‌شود و این دقیقا همان کدی است که توسط CLR خوانده و اجرا می‌شود. MSIL یک زبان طراحی شده مبتنی بر پشته‌ها است و بسیار شبیه به سایر زبان‌های اسمبلی موجود می‌باشد.


یک سؤال: آیا قطعه کدهای ذیل، کدهای IL یکسانی را تولید می‌کنند؟

namespace FastReflectionTests
{
    public class Test
    {
        public void Method1()
        {
            var x = 10;
            var y = 20;
            if (x == 10)
            {
                if (y == 20)
                {

                }
            }
        }

        public void Method2()
        {
            var x = 10;
            var y = 20;
            if (x == 10 && y == 20)
            {

            }
        }
    }
}
برای یافتن کدهای MSIL یا IL یک برنامه کامپایل شده می‌توان از ابزارهایی مانند Reflector یا ILSpy استفاده کرد. برای نمونه اگر از برنامه ILSpy استفاده کنیم چنین خروجی IL معادلی را می‌توان مشاهده کرد:
.class public auto ansi beforefieldinit FastReflectionTests.Test
extends [mscorlib]System.Object
{
// Methods
.method public hidebysig 
instance void Method1 () cil managed 
{
// Method begins at RVA 0x3bd0
// Code size 17 (0x11)
.maxstack 2
.locals init (
[0] int32 x,
[1] int32 y
)

IL_0000: ldc.i4.s 10
IL_0002: stloc.0
IL_0003: ldc.i4.s 20
IL_0005: stloc.1
IL_0006: ldloc.0
IL_0007: ldc.i4.s 10
IL_0009: bne.un.s IL_0010

IL_000b: ldloc.1
IL_000c: ldc.i4.s 20
IL_000e: pop
IL_000f: pop

IL_0010: ret
} // end of method Test::Method1

.method public hidebysig 
instance void Method2 () cil managed 
{
// Method begins at RVA 0x3bf0
// Code size 17 (0x11)
.maxstack 2
.locals init (
[0] int32 x,
[1] int32 y
)

IL_0000: ldc.i4.s 10
IL_0002: stloc.0
IL_0003: ldc.i4.s 20
IL_0005: stloc.1
IL_0006: ldloc.0
IL_0007: ldc.i4.s 10
IL_0009: bne.un.s IL_0010

IL_000b: ldloc.1
IL_000c: ldc.i4.s 20
IL_000e: pop
IL_000f: pop

IL_0010: ret
} // end of method Test::Method2

.method public hidebysig specialname rtspecialname 
instance void .ctor () cil managed 
{
// Method begins at RVA 0x3c0d
// Code size 7 (0x7)
.maxstack 8

IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method Test::.ctor

} // end of class FastReflectionTests.Test
همانطور که مشاهده می‌کنید، کدهای IL با یک برچسب شروع می‌شوند مانند IL_0000. پس از آن OpCodes یا Operation codes قرار دارند. برای مثال ldc کار load constant را انجام می‌دهد. به این ترتیب مقدار ثابت 10 بارگذاری شده و بر روی پشته ارزیابی قرار داده می‌شود و نهایتا در سمت راست، مقادیر را ملاحظه می‌کنید؛ برای مثال مقادیری مانند 10 و 20.
این کدها در حالت کامپایل Release تهیه شده‌اند و در این حالت، کامپایلر یک سری بهینه سازی‌هایی را جهت بهبود سرعت و کاهش تعداد OpCodes مورد نیاز برای اجرا برنامه، اعمال می‌کند.


بررسی OpCodes مقدماتی

الف) OpCodes ریاضی
مانند Add، Sub، Mul و Div

ب) OpCodes کنترل جریان برنامه
مانند Jmp، Beq، Bge، Ble، Bne، Call و Ret
برای پرش به یک برچسب، بررسی تساوی و بزرگتر یا کوچک بودن، فراخوانی متدها و بازگشت دادن مقادیر

ج) OpCodes مدیریت آرگومان‌ها
مانند Ldarg، Ldarg_0 تا Ldarg_3 ، Ldc_I4 و Ldc_I4_1 تا Ldc_I4_8
برای بارگذاری آرگومان‌‌ها و همچنین بارگذاری مقادیر قرار گرفته شده بر روی پشته ارزیابی.

برای توضیحات بهتر این موارد می‌توان کدهای IL فوق را بررسی کرد:
 IL_0000: ldc.i4.s 10
IL_0002: stloc.0
IL_0003: ldc.i4.s 20
IL_0005: stloc.1
IL_0006: ldloc.0
IL_0007: ldc.i4.s 10
IL_0009: bne.un.s IL_0010
IL_000b: ldloc.1
IL_000c: ldc.i4.s 20
IL_000e: pop
IL_000f: pop
در اینجا تعدادی مقدار بر روی پشته ارزیابی بارگذاری می‌شوند. تساوی آن‌ها بررسی شده و نهایتا متد خاتمه می‌یابد.


Stack چیست و MSIL چگونه عمل می‌کنید؟

Stack یکی از انواع بسیار متداول ساختار داده‌ها است و اگر بخواهیم خارج از دنیای رایانه‌ها مثالی را برای آن ارائه دهیم می‌توان به تعدادی برگه کاغذ که بر روی یکدیگر قرار گرفته‌اند، اشاره کرد. زمانیکه نیاز باشد تا برگه‌ای از این پشته برداشته شود، باید از بالاترین سطح آن شروع کرد که به آن LIFO یا Last in First out نیز گفته می‌شود. چیزی که آخر از همه بر روی پشته قرار می‌گیرد، در ابتدا برداشته و خارج خواهد شد.
در دات نت، برای قرار دادن اطلاعات بر روی Stack از متد Push و برای بازیابی از متد Pop استفاده می‌شود. استفاده از متد Pop، سبب خذف آن شیء از پشته نیز می‌گردد.
MSIL نیز یک Stack based language است. MSIL برای مدیریت یک سری از موارد از Stack استفاده می‌کند؛ مانند: پارامترهای متدها، مقادیر بازگشتی و انجام محاسبات در متدها. OpCodes کار قرار دادن و بازیابی مقادیر را از Stack به عهده دارند. به تمام این‌ها در MSIL، پشته ارزیابی یا Evaluation stack نیز می‌گویند.

یک مثال: فرض کنید می‌خواهید جمع 5+10 را توسط MSIL شبیه سازی کنیم.
الف) مقدار 5 بر روی پشته ارزیابی قرار داده می‌شود.
ب) مقدار 10 بر روی پشته ارزیابی قرار داده می‌شود. این مورد سبب می‌شود که 5 یک سطح به عقب رانده شود. به این ترتیب اکنون 10 بر روی پشته است و پس از آن 5 قرار خواهد داشت.
ج) سپس OpCode ایی مساوی Add فراخوانی می‌شود.
د) این OpCode سبب می‌شود تا دو مقدار موجود در پشته Pop شوند.
ه) سپس Add، حاصل عملیات را مجددا بر روی پشته قرار می‌دهد.


یک استثناء
در MSIL برای مدیریت متغیرهای محلی تعریف شده در سطح یک تابع، از Stack استفاده نمی‌شود. این مورد شبیه سایر زبان‌های اسمبلی است که در آن‌ها می‌توان مقادیر را در برچسب‌ها یا رجیسترهای خاصی نیز ذخیره کرد.
مطالب
کار با دیتاتایپ JSON در MySQL - قسمت اول
تا قبل از اضافه شدن دیتاتایپ JSON به صورت توکار در MySQL، داده‌های JSON را تنها میتوانستیم با فرمت رشته‌ای، درون دیتابیس ذخیره کنیم: 
CREATE TABLE tableName (
jsonData CHAR(250) -- or VARCHAR, TEXT, BLOB
);

INSERT INTO tableName VALUES (
'{ "name": "User1", "age": 41}'
);

SELECT * FROM tableName;

{ "name": "User1", "age": 41}
اما مشکل اینجاست که هیچ نوع اعتبارسنجی بر روی این دیتا صورت نخواهد گرفت؛ هیچ روشی برای مطمئن شدن از اینکه تگ‌ها به درستی استفاده شده‌اند، وجود ندارد و همچنین امکان جستجو را سخت خواهد کرد؛ زیرا مجبور خواهیم بود از Regular Expressions برای جستجوی درون متن‌های ذخیره شده استفاده کنیم:
SELECT * FROM tableName
WHERE jsonData REGEXP 'User1';

از نسخه MySQL 5.7.8 به بعد، می‌توانیم از نوع داده JSON برای ذخیره‌سازی محتوای JSON، استفاده کنیم. از این دیتاتایپ برای ذخیره‌سازی یک JSON document معتبر میتوان استفاده کرد:
CREATE TABLE tableName (
jsonData JSON
);

INSERT INTO tableName VALUES (
'{ "name": "User1", "age": 41, "name": "User2"}'
);

SELECT * FROM tableName;

{"age": 41, "name": "User2"}

همانطور که مشاهده میکنید MySQL به صورت اتوماتیک یکسری نرمال‌سازی را روی دیتا اعمال کرده است:
  • ابتدا بررسی خواهد شد که سند JSON معتبر باشد؛ در غیر اینصورت ذخیره‌سازی با مشکل مواجه خواهد شد.
  • از فیلدهایی که کلید تکراری دارند، صرفنظر خواهند شد. در مثال بالا دوبار فیلد name را مقداردهی کرده‌ایم. در اینجالت key/value دوم لحاظ شده‌است. البته میبایستی اصل first key wins لحاظ میشد، اما این مورد به عنوان یک باگ گزارش شده‌است و در نسخه‌های 8 به بعد رفع شده‌است (https://forums.mysql.com/read.php?3,660500,660500 - https://bugs.mysql.com/bug.php?id=86866).
  • فاصله‌های اضافی بین کلیدها حذف شده‌اند.
  • برای جستجوی بهتر، کلیدهای آبجکت JSON به صورت مرتب شده ذخیره شده‌اند.

جستجو درون JSON Document
یک سند JSON، از یکسری کلیدها به همراه مقادیرشان تشکیل شده‌است. همچنین مقادیر میتوانند شامل اشیاء یا آرایه‌هایی به صورت تودرتو باشند. بنابراین به یک path جهت استخراج مقادیر نیاز خواهیم داشت. برای نوشتن یک path باید scope آن را تعیین کنیم که در توابع MySQL این scope به صورت پیش‌فرض، سند جاری میباشد که توسط علامت $ مشخص میشود. 
فرض کنید ساختار زیر را درون دیتابیس ذخیره کرده‌ایم:
{
    "id": "1",
    "sku": "asdf123",
    "name": "Lorem ipsum jacket",
    "price": 12.45,
    "discount": 10,
    "offerEnd": "October 5, 2020 12:11:00",
    "new": false,
    "rating": 4,
    "saleCount": 54,
    "category": ["fashion", "men"],
    "tag": ["fashion", "men", "jacket", "full sleeve"],
    "variation": [
      {
        "color": "white",
        "image": "/assets/img/product/fashion/1.jpg",
        "size": [
          {
            "name": "x",
            "stock": 3
          },
          {
            "name": "m",
            "stock": 2
          },
          {
            "name": "xl",
            "stock": 5
          }
        ]
      },
      {
        "color": "black",
        "image": "/assets/img/product/fashion/8.jpg",
        "size": [
          {
            "name": "x",
            "stock": 4
          },
          {
            "name": "m",
            "stock": 7
          },
          {
            "name": "xl",
            "stock": 9
          },
          {
            "name": "xxl",
            "stock": 1
          }
        ]
      },
      {
        "color": "brown",
        "image": "/assets/img/product/fashion/3.jpg",
        "size": [
          {
            "name": "x",
            "stock": 1
          },
          {
            "name": "m",
            "stock": 2
          },
          {
            "name": "xl",
            "stock": 4
          },
          {
            "name": "xxl",
            "stock": 0
          }
        ]
      }
    ],
    "image": [
      "/assets/img/product/fashion/1.jpg",
      "/assets/img/product/fashion/3.jpg",
      "/assets/img/product/fashion/6.jpg",
      "/assets/img/product/fashion/8.jpg",
      "/assets/img/product/fashion/9.jpg"
    ],
    "description": {
      "shortDescription": "Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur.",
      "fullDescription": "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur? Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"
    }
  }

برای دریافت دسته‌بندی‌های هر ردیف میتوانیم از تابع JSON_EXTRACT استفاده کنیم:
SELECT 
    JSON_PRETTY(
  JSON_EXTRACT(data, "$.category")
    )
FROM
    experiments.productMetadata;

/* 
  [
    "fashion",
    "men"
  ]
  [
    "fashion",
    "women"
  ]
  [
    "fashion",
    "men"
  ]
*/
همانطور که مشاهده میکنید، تابع JSON_EXTRACT یک آرگومان دومی را نیز دریافت میکند که توسط آن میتوانیم path موردنظر را وارد کنیم و همانطور که عنوان شد، از $ برای دسترسی به سند جاری استفاده میکنیم. سپس در ادامه نام پراپرتی‌ای را که میخواهیم استخراج کنیم، تعیین کرده‌ایم. در اینجا چون ساختار ذخیره شده، به صورت شیء میباشد، به صورت مستقیم از $ و بعد از آن نقطه و سپس نام پراپرتی استفاده کرده‌ایم. میتوانیم عمق پیمایش را نیز بیشتر کنیم. به عنوان مثال برای دسترسی به المنت دوم از آرایه tag درون دیتا خواهیم داشت:
JSON_EXTRACT(data, "$.tag[1]")
JSON_EXTRACT(data, "$.description.shortDescription")

همچنین اگر کلید مقداری را که میخواهیم جستجو کنیم، بدانیم اما از کلید والد آن اطلاع نداشته باشیم، میتوانیم از * استفاده کنیم: 
SELECT 
JSON_EXTRACT(data, "$.*.shortDescription")
FROM experiments.productMetadata;

JSON_KEYS
از این تابع جهت دریافت کلیدهای top level یک شیء JSON استفاده میشود:
SELECT 
JSON_KEYS(data)
FROM experiments.productMetadata;

-- ["id", "new", "sku", "tag", "name", "image", "price", "rating", "category", "discount", "offerEnd", "saleCount", "variation", "description"]
-- ["id", "new", "sku", "tag", "name", "image", "price", "rating", "category", "discount", "saleCount", "variation", "description"]


همچنین میتوانیم path را نیز به عنوان آرگومان دوم آن تعیین کنیم: 
SELECT 
JSON_KEYS(data, "$.description")
FROM experiments.productMetadata;

-- ["fullDescription", "shortDescription"]
-- ["fullDescription", "shortDescription"]

JSON_CONTAINS 
از این تابع برای جستجو استفاده خواهیم کرد و همانطور که از نام آن پیداست، در صورت وجود مقدار مورد جستجو، خروجی ۱ خواهد بود:
SELECT 
    JSON_CONTAINS(data, "10", "$.discount")
FROM
    experiments.productMetadata;

-- 1
-- 0

JSON_CONTAINS_PATH
توسط این تابع میتوانیم بررسی کنیم که یک path یا یک یکسری path خاص درون JSON document وجود دارند یا خیر: 
SELECT 
JSON_CONTAINS_PATH(data, "one", "$.description", "$.address", "$.website")
FROM experiments.productMetadata;
آرگومان اول این تابع، داکیومنتی است که میخواهیم جستجو کنیم. برای آرگومان دوم، یکی از دو مقدار one یا all را میتوانیم تنظیم کنیم. در ادامه لیستی از pathهایی را که میخواهیم جستجو کنیم، وارد کرده‌ایم. در حالت one، اگر تنها یکی از pathها درون داکیومنت JSON وجود داشته باشند، خروجی ۱ خواهد بود. اگر one را به all تنظیم کنیم، یعنی باید تمامی pathها، درون داکیومنت وجود داشته باشند تا خروجی ۱ شود؛ در غیراینصورت خروجی ۰ خواهد بود. 

JSON_SEARCH  
توسط این تابع میتوانیم position مقدار مورد جستجو را درون داکیومنت JSON پیدا کنیم: 
SELECT 
    JSON_SEARCH(data, 'one', 'fashion')
FROM
    experiments.productMetadata;
    
-- "$.tag[0]"
-- "$.tag[0]"

مطالب
آشنایی و استفاده از WCF Data Services در Visualstudio 2012
مقدمه:

WCF Data Services جزئی از NET Framework است که امکان ایجاد سرویس دهنده‌های با قرارداد OData را به روی وب یا Intranet با استفاده از REST مهیا می‌سازد. OData از داده هایی که با Url آدرس پذیر هستند استفاده می‌نماید. دسترسی و تغییر داده‌ها با استفاده از استاندارد HTTP و کلمات GET، PUT، POST و DELETE صورت می‌پذیرد. برای اینکه درک بهتری داشته باشید به یک مثال می‌پردازیم.

ایجاد یک برنامه سرویس دهنده WCF Data Service در 2012 VisualStudio
  1. یک ASP.NET Web Application با نام NorthwindService ایجاد نمایید و بر روی پروژه راست کلیک کنید و از منوی Add گزینه New Item را انتخاب نمایید  از پنجره باز شده از دسته Data گزینه ADO.NET Entity Data Model  را انتخاب و نام ان را Northwind بگذارید.
  2. از پنجره باز شده Generate from Databaseرا انتخاب و با انتخاب کانکشن از نوع Sql Server Compact 4  اتصال به فایل Northwind.sdf را انتخاب تا کلاس‌های لازم تولید شود.
  3. برای تولید data service بر روی پروژه راست کلیک کنید و از منوی Add گزینه New Item را انتخاب نمایید از پنجره باز شده گزینه  WCF Data Service را انتخاب و نام آن را Northwind.svc بگذارید. کد زیر خودکار تولید می‌شود
     public class Northwind : DataService< /* TODO: put your data source class name here */ >
        {
            // This method is called only once to initialize service-wide policies.
            public static void InitializeService(DataServiceConfiguration config)
            {
                // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
                // Examples:
                // config.SetEntitySetAccessRule("MyEntityset", EntitySetRights.AllRead);
                // config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All);
                config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
            }
        }
  4. برای دسترسی به موجودیت‌های Northwind بجای عبارت put your data source نام مدل را تایپ کنید
    public class Northwind : DataService<NorthwindEntities>
  5. برای فعال کردن دسترسی به منابع data source متغیر config کلاس DataServiceConfiguration را بصورت زیر تنظیم نمایید. تابع SetEntitySetAccessRule با گرفتن نام موجودیت و نحوه دسترسی امکان استفاده از این موجودیت را با استفاده از WCF Data Service فزاهم می‌نمایید. مثلا در زیر امکان دسترسی به موجودیت Orders را با امکان خواندن همه، نوشتن ادقامی و جایگزین فراهم نموده است.
    config.SetEntitySetAccessRule("Orders", EntitySetRights.AllRead 
         | EntitySetRights.WriteMerge 
         | EntitySetRights.WriteReplace );
    config.SetEntitySetAccessRule("Customers", EntitySetRights.AllRead);
  6. اگر بخواهیم امکان خواندن همه موجودیت‌ها را فراهم کنیم از کد زیر می‌توانیم استفاده نمایید که * به معنای همه موجودیت‌های data model می‌باشد
    config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);

دسترسی به WCF Data Service بوسیله مرورگر وب
برای دسترسی به وب سرویس برنامه را اجرا نمایید تا آدرس http://localhost:8358/Northwind.svc مشخصات وب سرویس را نمایش دهد
<service xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom" xml:base="http://localhost:8358/Northwind.svc/">
<workspace>
<atom:title>Default</atom:title>
<collection href="Categories">
<atom:title>Categories</atom:title>
</collection>
<collection href="Customers">
<atom:title>Customers</atom:title>
</collection>
<collection href="Employees">
<atom:title>Employees</atom:title>
</collection>
<collection href="Order_Details">
<atom:title>Order_Details</atom:title>
</collection>
<collection href="Orders">
<atom:title>Orders</atom:title>
</collection>
<collection href="Products">
<atom:title>Products</atom:title>
</collection>
<collection href="Shippers">
<atom:title>Shippers</atom:title>
</collection>
<collection href="Suppliers">
<atom:title>Suppliers</atom:title>
</collection>
</workspace>
</service>
 حال اگر آدرس را به http://localhost:8358/Northwind.svc/Products وارد نمایید لیست کالا‌ها بصورت Atom xml قابل دسترس می‌باشد.
ایجاد یک برنامه گیرنده WCF Data Service در Visual Studio 2012
  1. بر روی Solution پروژه جاری راست کلیک و از منوی Add گزینه New Project را انتخاب و یک پروژه از نوع WPF Application با نام NorthwindClient ایجاد نمایید.
  2. در پنجره MainWindow مانند کد زیر از یک Combobox و DataGrid برای نمایش اطلاعات استفاده نمایید
        <Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Northwind Orders" Height="335" Width="425" 
            Name="OrdersWindow" Loaded="Window1_Loaded">
        <Grid Name="orderItemsGrid">
            <ComboBox DisplayMemberPath="Order_ID" ItemsSource="{Binding}"
                      IsSynchronizedWithCurrentItem="true" 
                      Height="23" Margin="92,12,198,0" Name="comboBoxOrder" VerticalAlignment="Top"/>
            <DataGrid ItemsSource="{Binding Path=Order_Details}"  
                      CanUserAddRows="False" CanUserDeleteRows="False"  
                      Name="orderItemsDataGrid" Margin="34,46,34,50"
                      AutoGenerateColumns="False">
                <DataGrid.Columns>
                    <DataGridTextColumn  Header="Product" Binding="{Binding Product_ID, Mode=OneWay}" />
                    <DataGridTextColumn  Header="Quantity" Binding="{Binding Quantity, Mode=TwoWay}" />
                    <DataGridTextColumn  Header="Price" Binding="{Binding UnitPrice, Mode=TwoWay}" />
                    <DataGridTextColumn  Header="Discount" Binding="{Binding Discount, Mode=TwoWay}" />                
                </DataGrid.Columns>     
            </DataGrid>
            <Label Height="28" Margin="34,12,0,0" Name="orderLabel" VerticalAlignment="Top" 
                   HorizontalAlignment="Left" Width="65">Order:</Label>
            <StackPanel Name="Buttons" Orientation="Horizontal" HorizontalAlignment="Right" 
                        Height="40" Margin="0,257,22,0">
                <Button Height="23" HorizontalAlignment="Right" Margin="0,0,12,12" 
                    Name="buttonSave" VerticalAlignment="Bottom" Width="75" 
                        Click="buttonSaveChanges_Click">Save Changes
                </Button>
                <Button Height="23" Margin="0,0,12,12" 
                    Name="buttonClose" VerticalAlignment="Bottom" Width="75" 
                        Click="buttonClose_Click">Close</Button>
            </StackPanel>
        </Grid>
    </Window>

  3. برای ارجاع به wcf data service بر روی پروژه راست کلیک و گزینه Add Service Reference را انتخاب نمایید در پنجره باز شده گزینه Discover را انتخاب تا سرویس را یافته و نام Namespase را Northwind بگذارید.
  4. حال مانند کد زیر یک شی از مدل NorthwindEntities با آدرس وب سرویس ایجاد نموده ایم و نتیحه کوئری با استفاده از کلاس DataServiceCollection به DataContext گرید انتصاب داده ایم که البته پیش فرض آن آشنایی با DataBinding در WPF است.
            private NorthwindEntities context;
            private string customerId = "ALFKI";
            private Uri svcUri = new Uri("http://localhost:8358/Northwind.svc");
    
            private void Window1_Loaded(object sender, RoutedEventArgs e)
            {
                try
                {
                    context = new NorthwindEntities(svcUri);
                    var ordersQuery = from o in context.Orders.Expand("Order_Details")
                                      where o.Customers.Customer_ID == customerId
                                      select o;
                    DataServiceCollection<Orders> customerOrders = new DataServiceCollection<Orders>(ordersQuery);
                    this.orderItemsGrid.DataContext = customerOrders;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
    
  5. با صدا زدن تابع SaveChanges مدل می‌توانید تغییرات را در پایگاه داده ذخیره نمایید.
    private void buttonSaveChanges_Click(object sender, RoutedEventArgs e)
    {
        try
        {
            context.SaveChanges();
        }
        catch (DataServiceRequestException ex)
        {
            MessageBox.Show(ex.ToString());
    
        }
    }

  1. برنامه را اجرا نمایید تا خروجی کار را مشاهده نمایید. مقادیر Quantity را تغییر دهید و دکمه Save Changes را انتخاب تا تغییرات دخیره شود.
در اینجا در یک برنامه ویندوزی استفاده از WCF Data Service را تست نمودیم اما براحتی به همین شیوه در یک برنامه وب نیز قابل استفاده است.  
نظرات مطالب
اعتبارسنجی مبتنی بر JWT در ASP.NET Core 2.0 بدون استفاده از سیستم Identity
استاندارد آن به این صورت است:
 Its value MUST be a number containing a NumericDate value.
و این NumericDate به نحو زیر باید تعریف شود (Section 2. Terminology):
 A JSON numeric value representing the number of seconds from 1970-01-01T00:00:00Z UTC until the specified UTC date/time, ignoring leap seconds. This is equivalent to the IEEE Std 1003.1, 2013 Edition [POSIX.1] definition "Seconds Since the Epoch", in which each day is accounted for by exactly 86400 seconds, other than that non-integer values can be represented. See RFC 3339 [RFC3339] for details regarding date/times in general and UTC in particular.
نمونه‌ی استفاده‌ی از آن در متد getAccessTokenExpirationDateUtc ارائه شده‌است.  
مطالب
آیا از وضعیت رویه‌های ذخیره شده‌ی دیتابیس‌های اس کیوال سرور خود خبر دارید؟

به لطف امکانات سیستمی اس کیوال سرورهای 2005 به بعد و DMV های آن‌ها، آمارگیری از ریز اتفاقات رخ داده در یک اس کیوال سرور این روزها بسیار ساده شده است و نیازی به ابزارهای جانبی برای انجام این نوع عملیات نیست (یا کمتر هست). در ادامه مروری خواهیم داشت بر یک سری کوئری که اطلاعات جالبی را در مورد وضعیت رویه‌های ذخیره شده‌ی دیتابیس‌های شما ارائه می‌دهند. لازم به ذکر است که اکثر این آمارها با هر بار ری استارت سرور، صفر خواهند شد.

آیا می‌دانید در یک دیتابیس خاص کدامیک از رویه‌های ذخیره شده‌ی شما بیش از سایرین مورد استفاده بود و آماری از این دست؟

use dbName;
SELECT TOP(100) qt.text AS 'SP Name',
qs.execution_count AS 'Execution Count',
qs.execution_count / DATEDIFF(Second, qs.creation_time, GETDATE()) AS
'Calls/Second',
qs.total_worker_time / qs.execution_count AS 'AvgWorkerTime',
qs.total_worker_time AS 'TotalWorkerTime',
qs.total_elapsed_time / qs.execution_count AS 'AvgElapsedTime',
qs.max_logical_reads,
qs.max_logical_writes,
qs.total_physical_reads,
DATEDIFF(Minute, qs.creation_time, GETDATE()) AS 'Age in Cache'
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS qt
WHERE qt.dbid = DB_ID() -- Filter by current database
ORDER BY
qs.execution_count DESC

البته مرتب سازی پیش فرض این کوئری بر اساس تعداد بار اجرا است (رویه‌های ذخیره شده‌ی محبوب!)، می‌شود آن‌را بر اساس total_worker_time (فشار بر روی CPU سیستم)، total_logical_reads (فشار بر روی حافظه)، total_physical_reads (فشار I/O کوئری‌ها)، total_logical_writes نیز مرتب کرد و نتایج جالب توجهی را بدست آورد.


آیا می‌دانید کدامیک از رویه‌های ذخیره شده‌ی شما بیش از سایرین کامپایل مجدد شده است؟

select top 50
sql_text.text,
sql_handle,
plan_generation_num,
execution_count,
dbid,
objectid
from
sys.dm_exec_query_stats a
cross apply sys.dm_exec_sql_text(sql_handle) as sql_text
where
plan_generation_num >1
order by plan_generation_num desc

آیا می‌دانید آخرین باری که رویه‌های ذخیره شده‌ی شما ویرایش شده‌اند چه زمانی بوده است؟

SELECT NAME,
create_date,
modify_date
FROM sys.objects
WHERE TYPE = 'P'
ORDER BY
Modify_Date DESC,
NAME

اشتراک‌ها
امکانات بیشتر و بهینه تر برای EF

این ابزار در نسخه رایگان شامل قابلیت‌های batch، کش، بهینه سازی و ... میباشد.

EF Include

var orders = ctx.Orders
                .Where(x => x.OrderId == myOrderID) // 1 orders, 20 columns
                .Include(x => x.Items) // 20 items, 10 columns
                .Include(x => x.DeliveredItems) // 10 items, 10 columns
                .ToList();

// return 20 + 10  = 30 rows
// return 20 + 10 + 10 = 40 columns
// total: 30 rows * 40 columns = 1200 cells transferred

EF+ IncludeOptimized

// SELECT * FROM Order WHERE....
// SELECT * FROM OrderItem WHERE EXISTS (/* previous query */) AND ...
// SELECT * FROM DeliveryItems WHERE EXISTS (/* previous query */) AND ...

var orders = ctx.Orders
                .Where(x => x.OrderId == myOrderID) // 1 orders, 20 columns
                .IncludeOptimized(x => x.Items) // 20 items, 10 columns
                .IncludeOptimized(x => x.DeliveredItems) // 10 items, 10 columns
                .ToList();

// return 1 row * 20 columns = 20 cells
// return 20 rows * 10 columns = 200 cells
// return 10 rows * 10 columns = 100 cells
// total: 20 + 200 + 100 = 320 cells transferred


امکانات بیشتر و بهینه تر برای EF
اشتراک‌ها
سری 47 قسمتی ساخت یک برنامه‌ی واقعی با Angular 10 و ASP.Net Core Web API

Build Real App in Angular 10 and ASP.Net Web API

These are 2 of the hottest frameworks right now for the ‘back-end’ (Microsoft’s ASP.NET Core) and the ‘front-end’ (Google’s Angular) and are well worth spending the time to learn.
This course starts from scratch, you neither need to know Angular 1 nor Angular 2
We will start from nothing and incrementally build this property dealing application front-end using Angular 10.
And then we will connect our front-end with the Web-API until we have a fully functional Web Application that we will publish to Firebase and then on IIS.

سری 47 قسمتی ساخت یک برنامه‌ی واقعی با  Angular 10 و ASP.Net Core Web API