اشتراک‌ها
چطور کارهامون رو به صورت Async انجام بدیم با استفاده از Channel و HostedService

چطور کارهامون رو به صورت Async انجام بدیم با استفاده از Channel و HostedService

I hope you are satisfied with this tutorial. In these two articles, we tried to tell you the ways in which we can do things with maximum efficiency in full Async, without worrying about the completion of the Request and the Disposal of our service. These have always been among the concerns of various programmers. And always using inefficient methods such as not leaving the word await 

چطور کارهامون رو به صورت Async انجام بدیم با استفاده از Channel و HostedService
مطالب دوره‌ها
چرا XML و چرا پشتیبانی توکار از آن در SQL Server
مقدمه

فیلدهای XML از سال 2005 به امکانات توکار SQL Server اضافه شده‌اند و بسیاری از مزایای دنیای NoSQL را درون SQL Server رابطه‌ای مهیا می‌سازند. برای مثال با تعریف یک فیلد به صورت XML، می‌توان از هر ردیف به ردیفی دیگر، اطلاعات متفاوتی را ذخیره کرد؛ به این ترتیب امکان کار با یک فیلد که می‌تواند اطلاعات یک شیء را قبول کند و در حقیقت امکان تعریف اسکیمای پویا و متغیر را در کنار امکانات یک بانک اطلاعاتی رابطه‌ای که از اسکیمای ثابت پشتیبانی می‌کند، میسر می‌شود.
همچنین SQL Server در این حالت قابلیتی را ارائه می‌دهد که در بسیاری از بانک‌های اطلاعاتی NoSQL میسر نیست. در اینجا در صورت نیاز و لزوم می‌توان اسکیمای کاملا مشخصی را به یک فیلد XML نیز انتساب داد؛ هر چند این مورد اختیاری است و می‌توان یک un typed XML را نیز بکار برد. به علاوه امکانات کوئری گرفتن توکار از این اطلاعات را به کمک XPath ترکیب شده با T-SQL، نیز فراموش نکنید.
بنابراین اگر یکی از اهداف اصلی گرایش شما به سمت دنیای NoSQL، استفاده از امکان تعریف اطلاعاتی با اسکیمای متغیر و پویا است، فیلدهای نوع XML اس کیوال سرور را مدنظر داشته باشید.
یک مثال عملی: فناوری Azure Dev Fabric's Table Storage (نسخه Developer ویندوز Azure که روی ویندوزهای معمولی اجرا می‌شود؛ یک شبیه ساز خانگی) به کمک SQL Server و فیلدهای XML آن طراحی شده است.



چرا XML و چرا پشتیبانی توکار از آن در SQL Server

یک سند XML معمولا بیشتر از یک قطعه داده را در خود نگهداری می‌کند و نوع داده‌ی پیچیده محسوب می‌شود؛ برخلاف داده‌هایی مانند int یا varchar که نوع‌هایی ساده بوده و تنها یک قطعه از اطلاعات خاصی را در خود نگهداری می‌کنند. بنابراین شاید این سؤال مطرح شود که چرا از این نوع داده پیچیده در SQL Server پشتیبانی شده‌است؟
- از سال‌های نسبتا دور، از XML برای انتقال داده‌ها بین سیستم‌ها و سکوهای کاری مختلف استفاده شده‌است.
- استفاده‌ی گسترده‌ای در برنامه‌های تجاری دارد.
- بسیاری از فناوری‌های موجود از آن پشتیبانی می‌کنند.
برای مثال اگر با فناوری‌های مایکروسافتی کار کرده باشید، به طور قطع حداقل در یک یا چند قسمت از آن‌ها، مستقیما از XML استفاده شده‌است.
بنابراین با توجه به اهمیت و گستردگی استفاده از آن، بهتر است پشتیبانی توکاری نیز از آن داخل موتور یک بانک اطلاعاتی، پیاده سازی شده باشد. این مساله سهولت تهیه پشتیبان‌های خودکار، بازیابی آن‌ها و امنیت یکپارچه با SQL Server را به همراه خواهد داشت؛ به همراه تمام زیرساخت‌های مهیای در SQL Server.



روش‌های مختلف ذخیره سازی XML در بانک‌های اطلاعاتی رابطه‌ای

الف) ذخیره سازی متنی
این روش نیاز به نگارش خاصی از SQL Server یا بانک اطلاعاتی الزاما خاصی نداشته و با تمام بانک‌های اطلاعاتی رابطه‌ای سازگار است؛ مثلا از فیلدهای varchar برای ذخیره سازی آن استفاده شود. مشکلی که این روش به همراه خواهد داشت، از دست دادن ارزش یک سند XML و برخورد متنی با آن است. زیرا در این حالت برای تعیین اعتبار آن یا کوئری گرفتن از آن‌ها نیاز است اطلاعات را از بانک اطلاعاتی خارج کرده و در لایه‌ای دیگر از برنامه، کار جستجو پردازش آن‌ها را انجام داد.

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

ج) ذخیره سازی آن‌ها توسط فیلدهای خاص XML
در این حالت با استفاده از فیلدهای ویژه XML می‌توان از فناوری‌های مرتبط با XML تمام و کمال استفاده کرد. برای مثال تهیه کوئری‌های پیچیده داخل همان بانک اطلاعاتی بدون نیاز به تجزیه سند به چندین جدول و یا خارج کردن آن‌ها از بانک اطلاعاتی و جستجوی بر روی آن‌ها در لایه‌ای دیگر از برنامه.


موارد کاربرد XML در SQL Server

کاربردهای مناسب

- اطلاعات، سلسله مراتبی و تو در تو هستند. XQuery و XPath در این موارد بسیار خوب عمل می‌کند.
- ساختار قسمتی از اطلاعات ثابت است و قسمتی از آن خیر. برای نمونه، یک برنامه‌ی فرم ساز را درنظر بگیرید که هر فرم آن هر چند دارای یک سری خواص ثابت مانند نام، گروه و امثال آن است، اما هر کدام دارای فیلدهای تشکیل دهنده متفاوتی نیز می‌باشد. به این ترتیب با استفاده از یک فیلد XML، دیگری نیازی به نگران بودن در مورد نحوه مدیریت اسکیمای متغیر مورد نیاز، نخواهد بود.
نمونه‌ی دیگر آن ذخیره سازی خواص متغیر اشیاء است. هر شیء دارای یک سری خواص ثابت است اما خواص توصیف کننده‌ی آن‌ها از هر رکورد به رکوردی دیگر متفاوت است.

کاربردهای نامناسب

- کل اطلاعات را داخل فیلد XML قرار دادن. هدف از فیلدهای XML قرار دادن یک دیتابیس داخل یک سلول نیست.
- ساختار تعریف شده کاملا مشخص بوده و به این زودی‌ها هم قرار نیست تغییر کند. در این حالت استفاده از قابلیت‌های رابطه‌ای متداول SQL Server مناسب‌تر است.
- قرار دادن اطلاعات باینری بسیار حجیم در سلول‌های XML ایی.
 


تاریخچه‌ی پشتیبانی از XML در نگارش‌های مختلف SQL Server

الف) SQL Server 2000
در SQL Server 2000 روش (ب) توضیح داده شده در قسمت قبل، پشتیبانی می‌شود. در آن برای تجزیه یک سند XML به معادل رابطه‌ای آن، از تابعی به نام OpenXML استفاده می‌شود و برای تبدیل این اطلاعات به XML از روش Select … for XML می‌توان کمک گرفت. همچنین تاحدودی مباحث XPath Queries نیز در آن گنجانده شد‌ه‌است.

ب) SQL Server 2005
در نگارش 2005 آن، برای اولین بار نوع داده‌ای ویژه XML معرفی گشت به همراه امکان تعریف اسکیمای XML و اعتبارسنجی آن و پشتیبانی از XQuery برای جستجوی سریع بر روی داده‌های XML داخل همان بانک اطلاعاتی، بدون نیاز به استخراج اطلاعات XML و پردازش مجزای آن‌ها در لایه‌ای دیگر از برنامه.

ج) SQL Server 2008 به بعد
در اینجا فاز نگهداری این نوع داده خاص شروع شده و بیشتر شامل یک سری بهبودهای کوچک در کارآیی و نحوه‌ی استفاده از آن‌ها می‌شود.



استفاده از XML با کمک SQLCLR

از SQL Server 2005 به بعد، امکان استفاده از کلیه‌ی امکانات موجود در فضای نام System.Xml دات نت، در SQL Server نیز به کمک SQL CLR مهیا شده‌است. همچنین از SQL Server 2008 به بعد، امکانات فضای نام System.Xml.Linq و مباحث LINQ to XML نیز توسط SQL CLR پشتیبانی می‌شوند.
البته این امکانات در SQL Server 2005 نیز قابل استفاده هستند، اما اسمبلی شما unsafe تلقی می‌شود. پس از آزمایشات و بررسی کافی، فضای نام مرتبط با LINQ to XML و امکانات آن، به عنوان اسمبلی‌هایی امن و قابل استفاده در SQL Server 2008 به بعد، معرفی شده‌اند.




مزایای وجود فیلد ویژه XML در SQL Server

پس از اینکه فیلدهای XML به صورت یک نوع داده بومی بانک اطلاعاتی SQL Server معرفی شدند، مزایای ذیل بلافاصله در اختیار برنامه نویس‌ها قرار گرفت:
- امکان تعریف آن‌ها به صورت یک ستون جدولی خاصی
- استفاده از آن‌ها به عنوان یک پارامتر رویه‌های ذخیره شده
- امکان تعریف خروجی توابع scalar سفارشی تعریف شده به صورت XML
- امکان تعریف متغیرهای T-SQL از نوع XML

برای مثال در اینجا نحوه‌ی تعریف یک جدول جدید دارای فیلدی از نوع XML را مشاهده می‌کنید:
 CREATE TABLE xml_tab
(
  id INT,
  xml_col  XML
)
- پشتیبانی از فناوری‌های XML ایی مانند اعتبارسنجی اسکیما و نوشتن کوئری‌های پیشرفته با XQuery و XPath.
- امکان تعریف ایندکس‌های XML ایی اضافه شده‌است.



چه نوع XML ایی را می‌توان در فیلدهای XML ذخیره کرد؟

فیلدهای XML امکان ذخیره سازی داده‌های XML خوش فرم را مطابق استاندارد یک XML، دارند. حداکثر اندازه قابل ذخیره سازی در یک فیلد XML دو گیگابایت است.
البته امکانات مهیای در SQL Server در بسیاری از موارد فراتر از استاندارد یک XML هستند. به این معنا که در فیلدهای XML می‌توان Documents و یا Fragments را ذخیره سازی کرد. یک سند XML یا Document حاوی تنها یک ریشه اصلی است؛ اما یک Fragment می‌تواند بیش از یک ریشه اصلی را در خود ذخیره کند. یک مثال:
 DECLARE @xml_tab TABLE (xml_col XML)
-- document
INSERT @xml_tab VALUES ('<person/>')
-- fragment
INSERT @xml_tab VALUES ('<person/><person/>')
SELECT * FROM @xml_tab
مدل داده‌ای XML در SQL Server بر مبنای استانداردهای  XQuery و XPath طراحی شده‌است و این استانداردها Fragments را به عنوان یک قطعه داده XML معتبر، قابل پردازش می‌دانند؛ علاوه بر آن مقادیر null و خالی را نیز معتبر می‌دانند. برای مثال عبارات ذیل معتبر هستند:
 DECLARE @xml_tab TABLE (xml_col XML)
-- text only
INSERT @xml_tab VALUES ('data data data .....')
-- empty string
INSERT @xml_tab VALUES ('')
-- null value
INSERT @xml_tab VALUES (null)
SELECT * FROM @xml_tab
همچنین امکان ذخیره سازی یک متن خالی بدون فرمت نیز در اینجا مجاز است. بنابراین به کمک T-SQL می‌توان برای مثال نوع داده varchar و varchar max را به XML تبدیل کرد و برعکس. امکان تبدیل Text و NText (منسوخ شده) نیز به XML وجود دارد ولی در این حالت خاص، عکس آن، پشتیبانی نمی‌شود.
به علاوه باید دقت داشت که در SQL Server نوع داده‌ای XML برای ذخیره سازی داده‌ها بکار گرفته می‌شود. به این معنا که در اینجا پیشوندهای فضاهای نام XML بی‌معنا هستند.
 DECLARE @xml_tab TABLE (xml_col XML)
INSERT @xml_tab VALUES ('<doc/>')
INSERT @xml_tab VALUES ('<doc xmlns="http://www.doctors.com"/>')
-- این سه سطر در عمل یکی هستند
INSERT @xml_tab VALUES ('<doc xmlns="http://www.documents.com"/>')
INSERT @xml_tab VALUES ('<dd:doc xmlns:dd="http://www.documents.com"/>')
INSERT @xml_tab VALUES ('<rr:doc xmlns:rr="http://www.documents.com"/>')
SELECT * FROM @xml_tab
در این مثال، سه insert آخر در عمل یکی درنظر گرفته می‌شوند.



Encoding ذخیره سازی داده‌های XML

SQL Server امکان ذخیره سازی اطلاعات متنی را به فرمت UFT8، اسکی و غیره، دارد. اما جهت پردازش فیلدهای XML و ذخیره سازی آن‌ها از Collation پیش فرض بانک اطلاعاتی کمک خواهد گرفت. البته ذخیره سازی نهایی آن همیشه با فرمت UCS2 است (یونیکد دو بایتی).
 DECLARE @xml_tab TABLE  (id INT, xml_col XML)

INSERT INTO @xml_tab
VALUES
  (
5,
N'<?xml version="1.0" encoding="utf-8"?>
<doc1>
  <row name="vahid"></row>
</doc1>
')
برای نمونه به مثال فوق دقت کنید. اگر آن‌را اجرا کنید، برنامه با خطای ذیل متوقف خواهد شد:
 XML parsing: line 1, character 38, unable to switch the encoding
علت اینجا است که با قرار دادن N در ابتدای رشته XML ایی در حال ذخیره سازی، آن‌را به صورت یونیکد دوبایتی معرفی کرده‌ایم اما encoding سند در حال ذخیره سازی utf-8 تعریف شده‌است و این‌دو با هم سازگاری ندارند.
برای حل این مشکل باید N ابتدای رشته را حذف کرد. روش دوم، معرفی و استفاده از utf-16 است بجای utf-8 در ویژگی encoding.
همچنین در این حالت اگر encoding را utf-16 معرفی کنیم و ابتدای رشته در حال ذخیره سازی N قرار نگیرد، باز با خطای unable to switch the encoding مواجه خواهیم شد.



نحوه‌ی ذخیره سازی اطلاعات XML ایی در SQL Server

SQL Server فرمت اطلاعات XML وارد شده را حفظ نمی‌کند. برای مثال اگر قطعه کد زیر را اجرا کنید
 DECLARE @xml_tab TABLE  (id INT, xml_col XML)

INSERT INTO @xml_tab
VALUES
  (
5,
'<?xml version="1.0" encoding="utf-8"?><doc1><row name="vahid"></row></doc1>'
  )
   
SELECT * FROM @xml_tab
خروجی Select انجام شده به صورت زیر است:
 <doc1>
  <row name="vahid" />
</doc1>
اطلاعات و داده نهایی، بدون تغییری از آن قابل استخرج است. اما اصطلاحا lexical integrity آن حفظ نشده و نمی‌شود. بنابراین در اینجا ذکر سطر xml version ضروری نیست و یا برای مثال اگر ویژگی‌ها را توسط " و یا ' مقدار دهی کنید، همیشه توسط "  ذخیره خواهد شد.



ذخیره سازی داده‌هایی حاوی کاراکترهای غیرمجاز XML

اطلاعات دنیای واقعی همیشه به همراه اطلاعات تک کلمه‌ای ساده نیست. ممکن است نیاز شود انواع و اقسام حروف و تگ‌ها نیز در این بین به عنوان داده ذخیره شوند. روش حل استاندارد آن بدون نیاز به دستکاری اطلاعات ورودی، استفاده از CDATA است:
 DECLARE @xml_tab TABLE  (id INT, xml_col XML)

INSERT INTO @xml_tab
VALUES
  (
5,
'<person><![CDATA[ 3 > 2 ]]></person>'
  )
   
SELECT * FROM @xml_tab
در این حالت خروجی select اطلاعات ذخیره شده به صورت زیر خواهد بود:
 <person> 3 &gt; 2 </person>
به صورت خودکار قسمت CDATA پردازش شده و اصطلاحا حروف غیرمجاز XML ایی به صورت خودکار escape شده‌اند.



محدودیت‌های فیلدهای XML

- امکان مقایسه مستقیم را ندارند؛ بجز مقایسه با نال. البته می‌توان XML را تبدیل به مثلا varchar کرد و سپس این داده رشته‌ای را مقایسه نمود. برای مقایسه با null توابع isnull و coalesce نیز قابل بکارگیری هستند.
- order by و group by بر روی این فیلدها پشتیبانی نمی‌شود.
- به عنوان ستون کلید قابل تعریف نیست.
- به صورت منحصربفرد و unique نیز قابل علامتگذاری و تعریف نیست.
- فیلدهای XML نمی‌توانند دارای collate باشند.
نظرات اشتراک‌ها
روش امن نگهداری پسورد کاربران
پیاده سازی روش گفته شده در این سایت :
/* 
 * Password Hashing With PBKDF2 (http://crackstation.net/hashing-security.htm).
 * Copyright (c) 2013, Taylor Hornby
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, 
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation 
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 * POSSIBILITY OF SUCH DAMAGE.
 */

using System;
using System.Text;
using System.Security.Cryptography;

namespace PasswordHash
{
    /// <summary>
    /// Salted password hashing with PBKDF2-SHA1.
    /// Author: havoc AT defuse.ca
    /// www: http://crackstation.net/hashing-security.htm
    /// Compatibility: .NET 3.0 and later.
    /// </summary>
    public class PasswordHash
    {
        // The following constants may be changed without breaking existing hashes.
        public const int SALT_BYTE_SIZE = 24;
        public const int HASH_BYTE_SIZE = 24;
        public const int PBKDF2_ITERATIONS = 1000;

        public const int ITERATION_INDEX = 0;
        public const int SALT_INDEX = 1;
        public const int PBKDF2_INDEX = 2;

        /// <summary>
        /// Creates a salted PBKDF2 hash of the password.
        /// </summary>
        /// <param name="password">The password to hash.</param>
        /// <returns>The hash of the password.</returns>
        public static string CreateHash(string password)
        {
            // Generate a random salt
            RNGCryptoServiceProvider csprng = new RNGCryptoServiceProvider();
            byte[] salt = new byte[SALT_BYTE_SIZE];
            csprng.GetBytes(salt);

            // Hash the password and encode the parameters
            byte[] hash = PBKDF2(password, salt, PBKDF2_ITERATIONS, HASH_BYTE_SIZE);
            return PBKDF2_ITERATIONS + ":" +
                Convert.ToBase64String(salt) + ":" +
                Convert.ToBase64String(hash);
        }

        /// <summary>
        /// Validates a password given a hash of the correct one.
        /// </summary>
        /// <param name="password">The password to check.</param>
        /// <param name="correctHash">A hash of the correct password.</param>
        /// <returns>True if the password is correct. False otherwise.</returns>
        public static bool ValidatePassword(string password, string correctHash)
        {
            // Extract the parameters from the hash
            char[] delimiter = { ':' };
            string[] split = correctHash.Split(delimiter);
            int iterations = Int32.Parse(split[ITERATION_INDEX]);
            byte[] salt = Convert.FromBase64String(split[SALT_INDEX]);
            byte[] hash = Convert.FromBase64String(split[PBKDF2_INDEX]);

            byte[] testHash = PBKDF2(password, salt, iterations, hash.Length);
            return SlowEquals(hash, testHash);
        }

        /// <summary>
        /// Compares two byte arrays in length-constant time. This comparison
        /// method is used so that password hashes cannot be extracted from
        /// on-line systems using a timing attack and then attacked off-line.
        /// </summary>
        /// <param name="a">The first byte array.</param>
        /// <param name="b">The second byte array.</param>
        /// <returns>True if both byte arrays are equal. False otherwise.</returns>
        private static bool SlowEquals(byte[] a, byte[] b)
        {
            uint diff = (uint)a.Length ^ (uint)b.Length;
            for (int i = 0; i < a.Length && i < b.Length; i++)
                diff |= (uint)(a[i] ^ b[i]);
            return diff == 0;
        }

        /// <summary>
        /// Computes the PBKDF2-SHA1 hash of a password.
        /// </summary>
        /// <param name="password">The password to hash.</param>
        /// <param name="salt">The salt.</param>
        /// <param name="iterations">The PBKDF2 iteration count.</param>
        /// <param name="outputBytes">The length of the hash to generate, in bytes.</param>
        /// <returns>A hash of the password.</returns>
        private static byte[] PBKDF2(string password, byte[] salt, int iterations, int outputBytes)
        {
            Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, salt);
            pbkdf2.IterationCount = iterations;
            return pbkdf2.GetBytes(outputBytes);
        }
    }
}
اشتراک‌ها
چگونه برنامه تحت دسکتاپ خود را به تحت NET Core 3.0. تبدیل کنید

In this post, I will describe how to port a desktop application from .NET Framework to .NET Core. I picked a WinForms application as an example. Steps for WPF application are similar and I’ll describe what needs to be done different for WPF as we go. I will also show how you can keep using the WinForms designer in Visual Studio even though it is under development and is not yet available for .NET Core projects. 

چگونه برنامه تحت دسکتاپ خود را به تحت NET Core 3.0. تبدیل کنید
اشتراک‌ها
9 نکته برای نوشتن برنامه های امن asp.net mvc

Security is one of the most important aspects of any application – and when we talk about security, particularly in ASP.NET applications, it is not limited to development. A secure app involves multiple layers of security in the configuration, framework, web server, database server, and more. In this post, we’ll take a look at the top nine tips for writing secure applications in ASP.NET. 

9 نکته برای نوشتن برنامه های امن asp.net mvc
اشتراک‌ها
5 دلیلی که زامارین توسعه برنامه های موبایل را تغییر خواهد داد

If you haven’t tried Xamarin yet, now is the time! Read this free white paper from Syncfusion to learn how Xamarin can improve your cross-platform development:

  • Deliver apps faster by sharing code across platforms, using one code base and UI.
  • Use best-in-class development tools, like Visual Studio.
  • Produce genuine native apps that don’t compromise the end user experience.
  • And more! 
5 دلیلی که زامارین توسعه برنامه های موبایل را تغییر خواهد داد
مطالب
کوئری نویسی در EF Core - قسمت هفتم - کار با رشته‌‌ها
هدف از این سری مثال‌ها، آشنایی با متدها و توابعی است که در حین کار با خواص رشته‌ای در LINQ to Entities، مجاز به استفاده‌ی از آن‌ها هستیم و همچنین اگر تابعی در EF-Core هنوز تعریف نشده بود، راه حل چیست.


مثال 1: نام تمام کاربران را با قالب 'Surname, Firstname'  نمایش دهید.

var members = context.Members
                                    .Select(member => new { Name = member.Surname + ", " + member.FirstName })
                                    .ToList();
متد Select می‌تواند به همراه اعمال محاسباتی ساده‌ای نیز باشد که نمونه‌ای از آن‌را در اینجا مشاهده می‌کنید.
با این خروجی:



مثال 2: تمام امکاناتی را که با Tennis شروع می‌شوند، لیست کنید.
این گزارش به همراه تمام ستون‌های جدول است.

var facilities = context.Facilities
                                        .Where(facility => facility.Name.StartsWith("Tennis"))
                                        .ToList();
متدهای استانداردی مانند StartsWith، EndsWith و Contains را می‌توان بر روی خواص رشته‌ای بکار برد.
با این خروجی:



مثال 3: تمام امکاناتی را که با tennis شروع می‌شوند، لیست کنید. این جستجو باید غیرحساس به بزرگی و کوچکی حروف باشد.
این گزارش به همراه تمام ستون‌های جدول است.

نیازی به انجام مجزای این تمرین نیست؛ چون پاسخ آن همان پاسخ مثال 2 است. Collation پیش‌فرض در SQL Server، غیرحساس به بزرگی و کوچکی حروف است. بنابراین چه tennis را جستجو کنیم و یا TeNnis را، تفاوتی نمی‌کند.


مثال 4: شماره تلفن‌های دارای پرانتز را لیست کنید.
این گزارش باید به همراه ستون‌های memid, telephone باشد.

روش اول: در اینجا دوبار از متد Contains استفاده شده‌است:
var members = context.Members
                                    .Select(member => new { member.MemId, member.Telephone })
                                    .Where(member => member.Telephone.Contains("(")
                                                    && member.Telephone.Contains(")"))
                                    .ToList();
با این خروجی:


روش دوم: اگر می‌خواهیم کنترل بیشتری را بر روی خروجی نهایی LIKE تولیدی داشته باشیم، می‌توان از متد سفارشی استاندارد EF.Functions.Like استفاده کرد که از حروف wild cards نیز پشتیبانی می‌کند:
members = context.Members
                                    .Select(member => new { member.MemId, member.Telephone })
                                    .Where(member => EF.Functions.Like(member.Telephone, "%[()]%"))
                                    .ToList();
با این خروجی:



مثال 5: کد پستی‌ها 5 رقمی هستند. گزارشی را تهیه کنید که در آن اگر کدپستی کمتر از 5 رقم بود، ابتدای آن با صفر شروع شود.
هدف اصلی از این مثال، اعمال متد PadLeft(5, '0') به خاصیت member.ZipCode است.

روش اول: EF-Core فعلا قابلیت ترجمه‌ی PadLeft(5, '0') را به معادل SQL آن‌را ندارد. به همین جهت مجبور هستیم ابتدا ZipCode‌ها را به صورت رشته‌ای بازگشت دهیم که در اینجا استفاده‌ی از Convert.ToString مجاز است.
با این خروجی:
SELECT   CONVERT (NVARCHAR (MAX), [m].[ZipCode]) AS [Zip]
FROM     [Members] AS [m]
ORDER BY CONVERT (NVARCHAR (MAX), [m].[ZipCode]);
 سپس می‌توان بر روی لیست آماده‌ی موجود در حافظه، از LINQ to Objects استفاده کرد و در این حالت دسترسی کاملی به تمام امکانات زبان #C وجود دارد:
var members = context.Members
                                    .Select(member => new { ZipCode = Convert.ToString(member.ZipCode) })
                                    .OrderBy(m => m.ZipCode)
                                    .ToList();
// Now using LINQ to Objects
members = members.Select(member => new { ZipCode = member.ZipCode.PadLeft(5, '0') })
                                                    .OrderBy(m => m.ZipCode)
                                                    .ToList();

روش دوم: SQL Server به همراه تابع استانداردی به نام Replicate است که از آن می‌توان برای شبیه سازی PadLeft، بدون متوسل شدن به LINQ to Objects، استفاده کرد. اما چون این تابع هنوز به EF-Core معرفی نشده‌است، نیاز است خودمان اینکار را انجام دهیم. در این روش، از متد SqlDbFunctionsExtensions.SqlReplicate استفاده می‌شود. روش تعریف این نوع متدها را در مطلب «امکان تعریف توابع خاص بانک‌های اطلاعاتی در EF Core» پیشتر بررسی کرده‌ایم که برای مثال در اینجا چنین شکلی را پیدا می‌کند:
namespace EFCorePgExercises.Utils
{
    public static class SqlDbFunctionsExtensions
    {
        public static string SqlReplicate(string expression, int count)
            => throw new InvalidOperationException($"{nameof(SqlReplicate)} method cannot be called from the client side.");

        private static readonly MethodInfo _sqlReplicateMethodInfo = typeof(SqlDbFunctionsExtensions)
            .GetRuntimeMethod(
                nameof(SqlDbFunctionsExtensions.SqlReplicate),
                new[] { typeof(string), typeof(int) }
            );


        public static void AddCustomSqlFunctions(this ModelBuilder modelBuilder)
        {
            modelBuilder.HasDbFunction(_sqlReplicateMethodInfo)
                .HasTranslation(args =>
                {
                    return SqlFunctionExpression.Create("REPLICATE",
                        args,
                        _sqlReplicateMethodInfo.ReturnType,
                        typeMapping: null);
                });
        }
    }
}
پس از آن فقط کافی است متد AddCustomSqlFunctions را به Context برنامه معرفی کنیم:
namespace EFCorePgExercises.DataLayer
{
    public class ApplicationDbContext : DbContext
    {
         // ...

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
         // ...
            modelBuilder.AddCustomSqlFunctions();
         // ...
        }
    }
}
اکنون می‌توان از تابع SqlDbFunctionsExtensions.SqlReplicate جهت شبیه سازی PadLeft به صورت زیر استفاده کرد:
var newMembers = context.Members
                                        .Select(member => new
                                        {
                                            ZipCode =
                                                SqlDbFunctionsExtensions.SqlReplicate(
                                                    "0", 5 - Convert.ToString(member.ZipCode).Length)
                                                + member.ZipCode
                                        })
                        .OrderBy(m => m.ZipCode)
                        .ToList();
با این خروجی:



مثال 6: اولین حرف نام خانوادگی کاربران در کل ردیف‌های جدول چندبار تکرار شده‌است؟
این گزارش باید به همراه ستون‌های letter,  count باشد.

var members = context.Members
                                    .Select(member => new { Letter = member.Surname.Substring(0, 1) })
                                    .GroupBy(m => m.Letter)
                                    .Select(g => new
                                    {
                                        Letter = g.Key,
                                        Count = g.Count()
                                    })
                                    .OrderBy(r => r.Letter)
                                    .ToList();
هدف از این مثال بیان مجاز بودن استفاده‌ی از متد Substring بر روی خواص رشته‌ای است که EF-Core امکان ترجمه‌ی آن‌ها را به کدهای SQL دارد.
با این خروجی:



مثال 7: حروف '-','(',')', ' ' را از شماره تلفن‌ها حذف کنید.
این گزارش باید به همراه ستون‌های memid, telephone باشد.

بانک اطلاعاتی PostgreSQL به همراه تابع استاندارد regexp_replace است و می‌توان از آن برای حل یک چنین مسایلی استفاده کرد:
select memid, regexp_replace(telephone, '[^0-9]', '', 'g') as telephone
from members
order by memid;
اما SQL Server هنوز هم به همراه یک چنین تابعی نیست. بنابراین از روش زیر نیز می‌توان مثال جاری را حل کرد:
var members = context.Members
                                .Select(member => new
                                {
                                    member.MemId,
                                    Telephone = member.Telephone.Replace("-", "")
                                                        .Replace("(", "")
                                                        .Replace(")", "")
                                                        .Replace(" ", "")
                                })
                                .OrderBy(r => r.MemId)
                                .ToList();
با این خروجی:



کدهای کامل این قسمت را در اینجا می‌توانید مشاهده کنید.
اشتراک‌ها
JSON.NET نسخه 7 منتشر شد
The JSON serializer in Json.NET is a good choice when the JSON you are reading or writing maps closely to a .NET class.LINQ to JSON is good for situations where you are only interested in getting values from JSON, you don't have a class to serialize or deserialize to, or the JSON is radically different from your class and you need to manually read and write from your objects. 
JSON.NET نسخه 7 منتشر شد
اشتراک‌ها
SQL Server® 2014 Service Pack 1 منتشر شد

A few of the customer-requested updates in Microsoft SQL Server 2014 SP1 are:

  • Column store performance is improved when batch mode operators spill over to disk. A new XEvent provides insights into column store inserts.
  • Several issues in buffer pool extension SSD configuration are addressed, including the ability to do instant initialization of the buffer pool extension file.
  • Certain queries compile faster when using new cardinality estimator, and other cardinality estimation query plans are more efficient when using TF-4199. 
  • The scalability benefits of two trace flags (TF-1236, TF-9024) are applied automatically.
  • Backup header information retrieval works better with encrypted backups.
SQL Server® 2014 Service Pack 1 منتشر شد