مطالب
تبدیل اعداد صحیح و اعشاری به حروف در T-SQL با استفاده از Join
استفاده شده از SQL 2008 

روش کار :

1-  دریافت پارامتر ورودی به صورت رشته
2-  درج عناوین اعداد، ارزش مکانی اعداد صحیح و اعشاری  هرکدام در یک جدول
3-  جدا کردن ارقام صحیح و اعشاری
4-  جداکردن سه رقم سه رقم اعداد صحیح و انتقال آنها به جدول مربوطه
5-  Join  جداول عناوین و ارقام جدا شده
6-  ارسال ارقام اعشاری به همین تابع
7-  مشخص کردن ارزش مکانی رقم اعشار
8-  اتصال رشته حروف صحیح و اعشاری

در آخر این مطلب کد این تابع را به صورت کامل، برای دانلود قرار داده ام.

بررسی قسمت‌های مختلف کد


برای اینکه محدودیتی در تعداد ارقام صحیح و اعشاری نداشته باشیم، پارامتر ورودی را از نوع VARCHAR می‌گیریم. پس باید ورودی را بررسی کنیم تا رشته عددی باشد.

بررسی رشته ورودی:

-- @pNumber   پارامتر ورودی

IF LEN(ISNULL(@pNumber, '')) = 0  RETURN NULL

IF (PATINDEX('%[^0-9.-]%', @pNumber) > 0)
   OR (LEN(@pNumber) -LEN(REPLACE(@pNumber, '-', '')) > 1)
   OR (LEN(@pNumber) -LEN(REPLACE(@pNumber, '.', '')) > 1)
   OR (CHARINDEX('-', @pNumber) > 1)
RETURN 'خطا'

IF PATINDEX('%[^0]%', @pNumber) = 0  RETURN 'صفر'
IF (CHARINDEX('.', @pNumber) = 1) SET @pNumber='0'+@pNumber

DECLARE @Negative AS VARCHAR(5) = '';
IF LEFT(@pNumber, 1) = '-'
BEGIN
    SET @pNumber = SUBSTRING(@pNumber, 2, 100)
    SET @Negative = 'منفی '
END
- بررسی NULL  ، خالی بودن و یا داشتن فاصله در رشته،  با دانستن اینکه تابع LEN  فاصله‌های آخر یک رشته را درنظر نمی‌گیرد.
- بررسی رشته ورودی برای پیدا کردن کاراکتر غیر عددی، نقطه و منفی. بررسی تعداد علامت منفی و نقطه که بیشتر از یک مورد نباشند، و در نهایت بررسی اینکه علامت منفی در ابتدای رشته ورودی باشد.
- بررسی صفر بودن ورودی(0)، مقدار ورودی شروع شونده با ممیز(0213. ) و مقدار عددی منفی(21210.0021-).
چیز دیگری به ذهنم نرسید!

درج عناوین در جداول مربوطه:

فکر کنم اینجا به علت وجود کاراکترهای فارسی و انگلیسی کد کمی بهم ریخته نمایش داده می‌شود.

DECLARE @NumberTitle TABLE (val  INT,Title NVARCHAR(100));
INSERT INTO @NumberTitle (val,Title)
VALUES(0, ''),(1, 'یک') ,(2, 'دو'),(3, 'سه'),(4, 'چهار')
,(5, 'پنج'),(6, 'شش'),(7, 'هفت'),(8, 'هشت')
,(9, 'نه'),(10, 'ده'),(11, 'یازده'),(12, 'دوازده')
,(13, 'سیزده'),(14, 'چهارده'),(15, 'پانزده'),(16, 'شانزده')
,(17, 'هفده'),(18, 'هجده'),(19, 'نوزده'),(20, 'بیست')
,(30, 'سی'),(40, 'چهل'),(50, 'پنجاه'),(60, 'شصت')
,(70, 'هفتاد'),(80, 'هشتاد'),(90, 'نود'),(100, 'صد')
,(200, 'دویست'),(300, 'سیصد'),(400, 'چهارصد'),(500, 'پانصد')
,(600, 'ششصد'),(700, 'هفتصد'),(800, 'هشتصد'),(900, 'نهصد')

DECLARE @PositionTitle TABLE (id  INT,Title NVARCHAR(100));
INSERT INTO @PositionTitle (id,title)
VALUES (1, ''),(2, 'هزار'),(3, 'میلیون'),(4, 'میلیارد'),(5, 'تریلیون')
,(6, 'کوادریلیون'),(7, 'کوینتیلیون'),(8, 'سیکستیلون'),(9, 'سپتیلیون')
,(10, 'اکتیلیون'),(11, 'نونیلیون'),(12, 'دسیلیون')
,(13, 'آندسیلیون'),(14, 'دودسیلیون'),(15, 'تریدسیلیون')
,(16, 'کواتردسیلیون'),(17, 'کویندسیلیون'),(18, 'سیکسدسیلیون')
,(19, 'سپتندسیلیون'),(20, 'اکتودسیلیوم'),(21, 'نومدسیلیون')

DECLARE @DecimalTitle TABLE (id  INT,Title NVARCHAR(100));
INSERT INTO @DecimalTitle (id,Title)
VALUES( 1 ,'دهم' ),(2 , 'صدم'),(3 , 'هزارم')
,(4 , 'ده-هزارم'),(5 , 'صد-هزارم'),(6 , 'میلیون ام')
,(7 , 'ده-میلیون ام'),(8 , 'صد-میلیون ام'),(9 , 'میلیاردم')
,(10 , 'ده-میلیاردم')


جداسازی رقم صحیح و اعشاری:

عدد ورودی ممکن است حالت‌های مختلفی داشته باشد مثل:         .00002 , 0.000000 , 234.434400000000 , 123.
بنابراین براساس ممیز، قسمت صحیح را از اعشاری جدا می‌کنیم. برای ورودی که با ممیز شروع شود، در ابتدا تابع بررسی می‌کنیم و عدد صفر را به رشته اضافه می‌کنیم.

بعد از ممیز و اعداد بزرگتر از یک، با صفرهای بی ارزش چه کنیم؟ شاید اولین چیزی که به ذهن برسد استفاده از حلقه (WHILE) برای حذف صفرهای بی ارزش قسمت ممیز باشد؛ ولی من ترجیح می‌دهم که از روش دیگری استفاده کنم :

برعکس کردن رشته قسمت اعشاری، پیدا کردن مکان اولین عدد غیر صفر منهای یک ، و کم کردن عدد بدست آمده از طول رشته اعشاری، قسمت مورد نظر ما را برخواهد گرداند:
SUBSTRING(@DecimalNumber,1, len(@DecimalNumber )-PATINDEX('%[^0]%', REVERSE (@DecimalNumber))-1)
 اما اگر عدد ورودی 20.0 باشد همچنان صفر بی ارزش بعداز ممیز را خواهیم داشت. برای رفع این مشکل کافی است که کاراکتری غیر از صفر را به اول رشته اعشاری اضافه کنیم. من از علامت '?' استفاده کردم. پس به علت اضافه کردن کاراکتر، استارت را از 2 شروع کرده و دیگر نیازی به -1 نخواهیم داشت. با کد زیر قسمت صحیح و اعشاری را بدست می‌آوریم:
DECLARE @IntegerNumber NVARCHAR(100),
@DecimalNumber NVARCHAR(100),
@PointPosition INT =case CHARINDEX('.', @pNumber) WHEN 0 THEN LEN(@pNumber)+1 ELSE CHARINDEX('.', @pNumber) END

SET @IntegerNumber= LEFT(@pNumber, @PointPosition - 1)
SET @DecimalNumber= '?' + SUBSTRING(@pNumber, @PointPosition + 1, LEN(@pNumber))
SET @DecimalNumber=  SUBSTRING(@DecimalNumber,2, len(@DecimalNumber )-PATINDEX('%[^0]%', REVERSE (@DecimalNumber)))

SET @pNumber= @IntegerNumber


جداد کردن سه رقم سه رقم :

- بدست آوردن یکان، دهگان و صدگان
- برای قسمت دهگان، اگر عددی بین 10 تا 19 باشد به صورت کامل (مثلا 15) و در غیر این صورت فقط رقم دهگان. برای بدست آوردن یکان اگر دو رقم آخر بین 10 و 19 بود صفر و در غیر این صورت یکان برگردانده می‌شود و در جدول MyNumbers درج می‌گردد. 
DECLARE @Number AS INT
DECLARE @MyNumbers TABLE (id INT IDENTITY(1, 1), Val1 INT, Val2 INT, Val3 INT)

WHILE (@pNumber) <> '0'
BEGIN
    SET @number = CAST(SUBSTRING(@pNumber, LEN(@pNumber) -2, 3)AS INT)
    
INSERT INTO @MyNumbers
SELECT (@Number % 1000) -(@Number % 100),
CASE 
WHEN @Number % 100 BETWEEN 10 AND 19 THEN @Number % 100
ELSE (@Number % 100) -(@Number % 10)
END,
CASE 
WHEN @Number % 100 BETWEEN 10 AND 19 THEN 0
ELSE @Number % 10
END
    
    IF LEN(@pNumber) > 2
        SET @pNumber = LEFT(@pNumber, LEN(@pNumber) -3)
    ELSE
        SET @pNumber = '0'
END

سطری که تمام مقادیر آن صفر باشد برای ما بی ارزش محسوب می‌شود، مانند سطر یک در عکس زیر (جدول MyNumbers) برای عدد 1200955000 :
@MyNumbers

استفاده از JOIN :

JOIN  کردن جدول اعداد با عناوین عددی براساس ارزش آن‌ها و JOIN  جدول اعداد با جدول ارزش مکانی براساس ID به صورت نزولی(شماره سطر).
DECLARE @Str AS NVARCHAR(2000) = '';
SELECT @Str += REPLACE(REPLACE(LTRIM(RTRIM(nt1.Title + ' ' + nt2.Title + ' ' + nt3.title)),'  ',' '),' ', ' و ')
       + ' ' + pt.title + ' و '
FROM   @MyNumbers  AS mn
       INNER JOIN @PositionTitle pt
            ON  pt.id = mn.id
       INNER JOIN @NumberTitle nt1
            ON  nt1.val = mn.Val1
       INNER JOIN @NumberTitle nt2
            ON  nt2.val = mn.Val2
       INNER JOIN @NumberTitle nt3
            ON  nt3.val = mn.Val3
WHERE  (nt1.val + nt2.val + nt3.val > 0)
ORDER BY pt.id DESC
Replace داخلی: جایگزین کردن "دو فاصله‌ی خالی" با "یک فاصله‌ی خالی"
Replace بیرونی: جایگزینی فاصله‌های خالی با ' و '
همانطور که در بالا اشاره کردم سطرهایی که val2,val1 و val3 آن صفر باشد برای ما بی ارزش هستند، پس آنها را با شرط نوشته شده حذف می‌کنیم.


بدست آوردن مقدار اعشاری:

خوب! حالا نوبت به عدد اعشاری می‌رسد. برای بدست آوردن حروف، مقدار اعشاری بدست آمده را به همین تابع ارسال می‌کنیم و برای بدست آوردن عنوان ارزش مکانی، براساس طول اعشار (ID) آن را در جدول مربوطه پیدا می‌کنیم.
اگر عدد ورودی مثلا 0.355 باشد، تابع باید صفر اول را شناسایی و قسمت عناوین اعشاری را به آن اضافه کند، که این کار با شرط ذیل انجام می‌شود.
اگر رشته اعشار بدون مقدار باشد، تابع مقدار NULL بر می‌گرداند (قسمت بررسی رشته ورودی) و هر رشته ای که با NULL جمع شود برابر با NULL خواهد بود. در این صورت با توجه به کد زیر مقداری به رشته Str به عنوان قسمت اعشاری، اضافه نمی‌گردد.
IF @IntegerNumber='0'  
SET @Str=CASE WHEN PATINDEX('%[^0]%', @DecimalNumber) > 0 THEN @Negative ELSE '' END + 'صفر'
ELSE
SET @Str = @Negative  + LEFT (@Str, LEN(@Str) -2)

DECLARE @PTitle NVARCHAR(100)=ISNULL((SELECT Title FROM @DecimalTitle WHERE id=LEN(@DecimalNumber)),'')
SET @Str += ISNULL(' ممیز '+[dbo].[fnNumberToWord_Persian](@DecimalNumber) +' '+@PTitle,'')
RETURN @str

مثال: رشته '5445789240.54678000000000'

پنج میلیارد و چهارصد و چهل و پنج میلیون و هفتصد و هشتاد و نه هزار و دویست و چهل  ممیز پنجاه و چهار هزار و ششصد و هفتاد و هشت  صد-هزارم  

دانلود فایل



مطالب
بررسی تصویر امنیتی (Captcha) سایت - قسمت دوم

در ادامه بررسی تصویر امنیتی سایت مواردی که باید پیاده سازی شود برای مورد اول میتوان کلاس زیر را در نظر گرفت که متدهایی برای تولید اعداد بصورت تصادفی در بین بازه معرفی شده را بازگشت میدهد:


// RandomGenerator.cs
using System;
using System.Security.Cryptography;

namespace PersianCaptchaHandler
{
    public class RandomGenerator
    {
        private static readonly byte[] Randb = new byte[4];
        private static readonly RNGCryptoServiceProvider Rand = new RNGCryptoServiceProvider();

        public static int Next()
        {
            Rand.GetBytes(Randb);
            var value = BitConverter.ToInt32(Randb, 0);
            if (value < 0) value = -value;
            return value;
        }
        public static int Next(int max)
        {
            Rand.GetBytes(Randb);
            var value = BitConverter.ToInt32(Randb, 0);
            value = value%(max + 1);
            if (value < 0) value = -value;
            return value;
        }
        public static int Next(int min, int max)
        {
            var value = Next(max - min) + min;
            return value;
        }
    }
}
و برای تبدیل عدد تصادفی بدست آمده به متن نیز از این کلاس میتوان استفاده کرد که به طرز ساده ای این کار را انجام میدهد:
// NumberToString.cs
namespace PersianCaptchaHandler
{
    public class NumberToString
    {

        #region Fields
        private static readonly string[] Yakan = new[] { "صفر", "یک", "دو", "سه", "چهار", "پنج", "شش", "هفت", "هشت", "نه" };
        private static readonly string[] Dahgan = new[] { "", "", "بیست", "سی", "چهل", "پنجاه", "شصت", "هفتاد", "هشتاد", "نود" };
        private static readonly string[] Dahyek = new [] { "ده", "یازده", "دوازده", "سیزده", "چهارده", "پانزده", "شانزده", "هفده", "هجده", "نوزده" };
        private static readonly string[] Sadgan = new [] { "", "یکصد", "دوصد", "سیصد", "چهارصد", "پانصد", "ششصد", "هفتصد", "هشتصد", "نهصد" };
        private static readonly string[] Basex = new [] { "", "هزار", "میلیون", "میلیارد", "تریلیون" };
        #endregion

        private static string Getnum3(int num3)
        {
            var s = "";
            var d12 = num3 % 100;
            var d3 = num3 / 100;
            if (d3 != 0)
                s = Sadgan[d3] + " و ";
            if ((d12 >= 10) && (d12 <= 19))
            {
                s = s + Dahyek[d12 - 10];
            }
            else
            {
                var d2 = d12 / 10;
                if (d2 != 0)
                    s = s + Dahgan[d2] + " و ";
                var d1 = d12 % 10;
                if (d1 != 0)
                    s = s + Yakan[d1] + " و ";
                s = s.Substring(0, s.Length - 3);
            }
            return s;
        }

        public static string ConvertIntNumberToFarsiAlphabatic(string snum)
        {
            var stotal = "";
            if (snum == "0") return Yakan[0];

            snum = snum.PadLeft(((snum.Length - 1) / 3 + 1) * 3, '0');
            var l = snum.Length / 3 - 1;
            for (var i = 0; i <= l; i++)
            {
                var b = int.Parse(snum.Substring(i * 3, 3));
                if (b != 0)
                    stotal = stotal + Getnum3(b) + " " + Basex[l - i] + " و ";
            }
            stotal = stotal.Substring(0, stotal.Length - 3);
            return stotal;
        }
    }
}
و برای کد کردن و دیکد کردن یعنی موارد سوم و چهارم مقاله قبلی، متن بدست آمده را که بعنوان قسمتی از آدرس تصویر در ادامه آدرس هندلر معرفی شده می‌آید تبدیل به یک string بی معنی برای بازدیدکننده میکند:

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

namespace PersianCaptchaHandler
{
    public class Encryptor
    {
        #region constraints
        private static string Password { get { return "Mehdi"; } }
        private static string Salt { get { return "Payervand"; } }
        #endregion

        public static string Encrypt(string clearText)
        {
            // Turn text to bytes
            var clearBytes = Encoding.Unicode.GetBytes(clearText);

            var pdb = new PasswordDeriveBytes(Password, Encoding.Unicode.GetBytes(Salt));

            var ms = new MemoryStream();
            var alg = Rijndael.Create();

            alg.Key = pdb.GetBytes(32);
            alg.IV = pdb.GetBytes(16);

            var cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write);

            cs.Write(clearBytes, 0, clearBytes.Length);
            cs.Close();

            var encryptedData = ms.ToArray();

            return Convert.ToBase64String(encryptedData);
        }
        public static string Decrypt(string cipherText)
        {
            // Convert text to byte
            var cipherBytes = Convert.FromBase64String(cipherText);

            var pdb = new PasswordDeriveBytes(Password, Encoding.Unicode.GetBytes(Salt));

            var ms = new MemoryStream();
            var alg = Rijndael.Create();

            alg.Key = pdb.GetBytes(32);
            alg.IV = pdb.GetBytes(16);

            var cs = new CryptoStream(ms, alg.CreateDecryptor(), CryptoStreamMode.Write);

            cs.Write(cipherBytes, 0, cipherBytes.Length);
            cs.Close();

            var decryptedData = ms.ToArray();

            return Encoding.Unicode.GetString(decryptedData);
        }
    }
}


و نیز برای اعتبار سنجی عدد دریافتی از کاربر میتوان از عبارت با قاعده زیر استفاده کرد:

// Utils.cs
using System.Text.RegularExpressions;

namespace PersianCaptchaHandler
{
    public class Utils
    {
        private static readonly Regex NumberMatch = new Regex(@"^([0-9]*|\d*\.\d{1}?\d*)$", RegexOptions.Compiled);
        public static bool IsNumber(string number2Match)
        {
            return NumberMatch.IsMatch(number2Match);
        }
    }
}
برای استفاده نیز کافیست که هندلر مربوط به این کتابخانه را بطریق زیر در وب کانفیگ رجیستر کرد:

<add verb="GET" path="/captcha/" type="PersianCaptchaHandler.CaptchaHandler, PersianCaptchaHandler, Version=1.0.0.0, Culture=neutral"  />
و در صفحه مورد نظرتان بطریق زیر میتوان از یک تگ تصویر برای نمایش تصویر تولیدی و از یک فیلد مخفی برای نگهداری مقدار کد شده معادل عدد تولیدی که در هنگام مقایسه با عدد ورودی کاربر مورد نیاز است استفاده شود:

<!-- ASPX -->
<dl>
    <dt>تصویر امنیتی</dt>
    <dd>
        <asp:Image ID="imgCaptchaText" runat="server" AlternateText="CaptchaImage" />
        <asp:HiddenField ID="hfCaptchaText" runat="server" />
        <asp:ImageButton ID="btnRefreshCaptcha" runat="server" ImageUrl="/img/refresh.png"
            OnClick="btnRefreshCaptcha_Click" />
        <br />
        <asp:TextBox ID="txtCaptcha" runat="server" AutoCompleteType="Disabled"></asp:TextBox>
    </dd>
    <dd>
        <asp:Button ID="btnSubmit" runat="server" Text="ثبت" OnClick="btnSubmit_Click" />
    </dd>
</dl>
<asp:Label ID="lblMessage" runat="server"></asp:Label>
در زمان لود صفحه، تصویر امنیتی مقدار دهی میشود و در زمان ورود عدد توسط کاربر با توجه به اینکه کاربر حتما باید عدد وارد کند با عبارت با قاعده این اعتبار سنجی انجام میشود:

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
                SetCaptcha();
        }

        private void SetCaptcha()
        {
            lblMessage.Text =
            txtCaptcha.Text = string.Empty;

            var newNumber =
                RandomGenerator.Next(100, 999)
                ;

            var farsiAlphabatic = NumberToString.ConvertIntNumberToFarsiAlphabatic(newNumber.ToString());

            hfCaptchaText.Value =
                HttpUtility
                .UrlEncode(
                    Encryptor.Encrypt(
                        farsiAlphabatic
                    )
                );

            txtCaptcha.Text = string.Empty;
            imgCaptchaText.ImageUrl =
                "/captcha/?text=" + hfCaptchaText.Value;
        }
و بعد از ورود عدد از سمت کاربر از متد تبدیل به حروف استفاده کرده و این مقدار تولیدی با مقدار فیلد مخفی مقایسه میشود:
        private string GetCaptcha()
        {
            var farsiAlphabatic = NumberToString.ConvertIntNumberToFarsiAlphabatic(txtCaptcha.Text);

            var encryptedString =
                HttpUtility
                .UrlEncode(
                    Encryptor.Encrypt(
                        farsiAlphabatic
                    )
                );

            return encryptedString;
        }

        private bool ValidateUserInputForLogin()
        {
            if (!Utils.IsNumber(txtCaptcha.Text))
            {
                lblMessage.Text = "تصویر امنیتی را بطور صحیح وارد نکرده اید";
                return false;
            }

            var strGetCaptcha =
                GetCaptcha();

            var strDecodedVAlue =
                hfCaptchaText.Value;

            if (strDecodedVAlue != strGetCaptcha)
            {
                lblMessage.Text = "کلمه امنیتی اشتباه است";
                SetCaptcha();
                return false;
            }
            return true;
        }

        protected void btnSubmit_Click(object sender, EventArgs e)
        {
            if (!ValidateUserInputForLogin()) return;
            lblMessage.Text = "کلمه امنیتی درست است";
        }

        protected void btnRefreshCaptcha_Click(object sender, ImageClickEventArgs e)
        {
            SetCaptcha();
        }
 در آخر این پروژه در کدپلکس قرار داده شده، و مشتاق نظرات و پیشنهادات شما هستم و نیز نمونه مثال بالا ضمیمه شده است
اشتراک‌ها
پیاده سازی یک پروژه با ASP.NET Core Web API

Ticketier project | ASP.NET Core Web API CRUD and Search | .NET 7 API | Full Course

Full Course Ticketier project with ASP.NET Core Web API (.NET 7 API ) and  Entity Framework Core covering CRUD and Search step by step
In this video, we will create an ASP.NET Core Web API (.NET 7) project called Ticketier and implement full CRUD and Search functionality into it.
The focus of this project is to show you how you can build new ASP.NET Core Web API (.NET 7) project from 0 to 100 and implement CRUD and Search in it.

we will learn these topics together:
Entities
Dtos
Context
ORM
Http Methods
Swagger
AutoMapper
IQueryable
Where clause 

پیاده سازی یک پروژه با ASP.NET Core Web API
اشتراک‌ها
ساخت یک بازی آنلاین با Blazor و دات نت 7

Spawn an Online Game with Blazor, .NET 7 and Clean Architecture in under 60 minutes

In this fun talk, Luke Parker will show you step-by-step how to build a playable game in under 60 minutes. He will go over some basic game design, project planning, then build the game and finally… play live with the audience! Utilizing code sharing and the magic of Clean Architecture allows for very rapid app development. Also, leveraging MudBlazor as the component library lets you save time and to focus on what really matters.
 

ساخت یک بازی آنلاین با Blazor و دات نت 7
اشتراک‌ها
کتابخانه Hangfire

An easy way to perform background job processing in your .NET and .NET Core applications. No Windows Service or separate process required. CPU and I/O intensive, long-running and short-running jobs are supported. Backed by Redis, SQL Server, SQL Azure and MSMQ. 

PM> Install-Package Hangfire

After installation, update your existing OWIN Startup file with the following lines of code. If you do not have this class in your project or don't know what is it, please read the Quick start guide to learn about how to install Hangfire.

public void Configuration(IAppBuilder app)
{
    GlobalConfiguration.Configuration.UseSqlServerStorage("<connection string or its name>");
    
    app.UseHangfireServer();
    app.UseHangfireDashboard();
}  
کتابخانه Hangfire
اشتراک‌ها
خروجی‌های Covariant به زودی در NET runtime.

Work in progress to add support for covariant return types to the .NET runtime. Soon we'll be able to override a virtual method returning `object` with a method returning `string`. Because of how array variance works, weird things might be possible in IL. 

class Base
{
    public virtual IntPtr[] Fun() => null;
}

// This is obvious pseude-code because C# won't let us introduce methods differing
// in return type. C# also requires to be explicit about "virtual" and "override".
// But IL... not so much.
class Derived : Base
{
    // overrides Base.Fun on 32bit platforms.
    public override uint[] Fun() => null;

    // overrides Base.Fun on 64bit platforms.
    public override ulong[] Fun() => null;
}
خروجی‌های Covariant به زودی در NET runtime.
اشتراک‌ها
اعتبارسنجی کاربران بدون هاردکد کردن نقشها

You already know how role-based authorization works in ASP.NET Core.

[Authorize(Roles = "Administrator")]
public class AdministrationController : Controller
{
}

But what if you don't want hardcode roles on the Authorize attribute or create roles later and specify in which controller and action it has access without touching source code?

DynamicAuthorization helps you authorize users without hardcoding role(s) on the Authorize attribute with minimum effort. DynamicAuthorization is built at the top of ASP.NET Core Identity and use identity mechanism for managing roles and authorizing users. 

اعتبارسنجی کاربران بدون هاردکد کردن نقشها
اشتراک‌ها
بهبودهای EF Core 2.1 در زمینه پشتیبانی از DDD

Entity Framework half-heartedly supported Domain-Driven Design patterns. But the new-from-scratch EF Core has brought new hope for developers to map your well-designed domain classes to a database, reducing the cases where a separate data model is needed. EF Core 2.1 is very DDD friendly, even supporting things like fully encapsulated collections, backing fields and the return of support for value objects. In this session, we'll review some well-designed aggregates and explore how far EF Core 2.1 goes to act as the mapper between your domain classes and your data store. 

بهبودهای EF Core 2.1 در زمینه پشتیبانی از DDD