‫۵ سال و ۱ ماه قبل، یکشنبه ۱۳ مرداد ۱۳۹۸، ساعت ۲۰:۳۲
بهتر است با امکانات «کتابخانه‌ی moment-jalaali» بیشتر آشنا شوید و برای تبدیل حالات مختلف (شمسی به میلادی و برعکس) از آن استفاده کنید. مثال‌های بیشتر آن‌را در اینجا پیگیری کنید (مطابق نگارشی که در این مطلب استفاده شده).
‫۵ سال و ۱ ماه قبل، یکشنبه ۱۳ مرداد ۱۳۹۸، ساعت ۱۶:۴۳
ارتقاء به ASP.NET Core 3.0 و تغییرات نقطه‌ی آغازین برنامه

ASP.NET Core 3.0 از Generic Host بجای Web Host قبلی استفاده می‌کند. در این حالت فایل Program.cs آن از:
public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}
در نگارش 2.2، به حالت زیر در نگارش 3 تغییر یافته‌است:
public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}
البته باید درنظر داشت که روش قبلی 2.2، هنوز هم در نگارش 3 کار می‌کند، اما به صورت deprecated و منسوخ شده معرفی خواهد شد و در نگارش‌های بعدی حذف می‌گردد.
در این حالت هاستینگ برنامه دیگر به Kestrel و یا حتی خود ASP.NET Core وابسته نخواهد بود. یعنی می‌توان هاستی را ایجاد کرد که به همراه راه اندازی وب سرور Kestrel نباشد. علت این جنریک شدن چیست؟
در نگارش سوم، هاست‌های دیگری هم معرفی شده‌اند؛ مانند امکان اجرای یک worker service بدون راه اندازی یک وب سرور و یا Blazor از روش هاستینگ متفاوتی درون یک web assembly استفاده می‌کند: «ارتقاء به NET Core 3.0.: پشتیبانی از ایجاد سرویس‌های پس‌زمینه»

یک نکته: جزئیات متد CreateDefaultBuilder و سرویس‌هایی را که به صورت خودکار اضافه می‌کند، در اینجا در فایل src/DefaultBuilder/src/WebHost.cs می‌توانید مشاهده کنید.
‫۵ سال و ۱ ماه قبل، یکشنبه ۱۳ مرداد ۱۳۹۸، ساعت ۱۵:۵۷
ارتقاء به ASP.NET Core 3.0 و سرنوشت metapackageهای Microsoft.AspNetCore

پس از نصب SDK جدید، اگر دستور dotnet new mvc را صادر کنید، فایل csproj تولید شده‌ی آن تنها دارای TargetFramework ای معادل netcoreapp3.0 است و نه هیچ مورد دیگری:
<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
  </ItemGroup>
</Project>
بنابراین برای ارتقاء پروژه‌های قبلی به نگارش 3 آن:
- ابتدا TargetFramework را به netcoreapp3.0 تنظیم کنید.
- سپس تمام PackageReferenceهایی را که به بسته‌های Microsoft.AspNetCore.All و یا Microsoft.AspNetCore.App اشاره می‌کنند، حذف کنید.
- ارجاع به بسته‌ی Microsoft.AspNetCore.Razor.Design را نیز حذف کنید.
- اگر پیشتر خاصیت AspNetCoreHostingModel را به حالت درون پروسه‌ای تنظیم کرده‌اید، آن‌را حذف کنید؛ چون حالت پیش‌فرض نگارش 3 است.
- حذف شدن JSON.NET را مدنظر داشته باشید.
- تغییرات حالت ثبت سرویس‌های MVC و Razor Pages و Web API را مدنظر داشته باشید.
- مسیریابی آن نیز Endpoint routing شده‌است.
- نقطه‌ی آغازین آن نیز بازنویسی شده‌است.
‫۵ سال و ۱ ماه قبل، شنبه ۱۲ مرداد ۱۳۹۸، ساعت ۱۹:۱۰
یک نکته‌ی تکمیلی: چگونه یک Pull Request ارسالی را به روز کنیم؟
- ابتدا تغییرات مدنظر را به مخزن کد محلی خود اعمال کنید (همان مخزنی که معادل نمونه‌ی fork شده‌ی مخزن راه دور است).
- سپس این تغییرات را به مخزن کد fork شده موجود در GitHub نیز اعمال کنید.
با اینکار Pull request شما در GitHub نیز به صورت خودکار به روز رسانی می‌شود.
‫۵ سال و ۱ ماه قبل، شنبه ۱۲ مرداد ۱۳۹۸، ساعت ۱۸:۱۸
تنظیمات appveyor مخصوص NET Core 3.0 Prview.

- انتخاب محیط Build به صورت «Visual Studio 2019 preview»، از این جهت که نگارش preview به همراه آخرین SDK است.
- سپس قفل کردن شماره SDK در پروژه‌ی خود، با افزودن فایل global.json
 dotnet new globaljson --sdk-version 3.0.100-preview7-012821
البته ممکن است این نگارش را نصب نکرده باشد؛ به همین جهت برای نصب آن، به قسمت environment پروژه مراجعه کرده و در پایین صفحه در قسمت Init script، بر روی گزینه‌ی PS کلیک کرده و سپس دستورات زیر را در آنجا کپی و ذخیره کنید:
$urlCurrent = "https://download.visualstudio.microsoft.com/download/pr/41e4c58f-3ac9-43f6-84b6-f57d2135331a/3691b61f15f1f5f844d687e542c4dc72/dotnet-sdk-3.0.100-preview7-012821-win-x64.zip"
$env:DOTNET_INSTALL_DIR = "C:\Program Files\dotnet\sdk"
mkdir $env:DOTNET_INSTALL_DIR -Force | Out-Null
$tempFileCurrent = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName())
(New-Object System.Net.WebClient).DownloadFile($urlCurrent, $tempFileCurrent)
Add-Type -AssemblyName System.IO.Compression.FileSystem; [System.IO.Compression.ZipFile]::ExtractToDirectory($tempFileCurrent, $env:DOTNET_INSTALL_DIR)
$env:Path = "$env:DOTNET_INSTALL_DIR;$env:Path"
این دستورات فایل dotnet-sdk-3.0.100-preview7-012821-win-x64.zip را دریافت کرده (فایل zip هست و نه exe؛ یا همان NET Core Binaries.) و در یک مکان موقتی ذخیره می‌کنند. سپس آن‌را در پوشه‌ی SDKها جهت استفاده‌ی نهایی، باز می‌کنند.
اکنون اگر به قسمت current build مراجعه و یک build جدید را شروع کنید، ابتدا SDK جدید را دریافت و نصب می‌کند. سپس بر این اساس شروع به Build پروژه می‌کند.
‫۵ سال و ۱ ماه قبل، شنبه ۱۲ مرداد ۱۳۹۸، ساعت ۰۰:۰۳
- خیر. سطح اول کش در EF 6x فقط به معنای استفاده از متد FindAsync و Find آن است و نه هیچ متد دیگری.
- فراخوانی متد ToList بر روی یک IEnumerable، اتصال آن‌را از بانک اطلاعاتی قطع می‌کند. به همین جهت اگر list نوشته شده (var list = ctx.ProjectStatus.Select )، یک ToList را در انتها داشت، دو حلقه‌ی بعدی فقط LINQ to Objects می‌شدند (از حافظه خوانده می‌شدند)؛ اما در حالت فعلی آن، هر دو مورد LINQ to Entities هستند و متصل به بانک اطلاعاتی.
- البته این مورد متصل بودن به بانک اطلاعاتی، می‌تواند مزیت هم باشد. برای مثال ToList، ابتدا تمام رکوردها را به درون حافظه بارگذاری می‌کند؛ اما اگر صرفا با خروجی Select که از نوع IEnumerable هست کار کنید، هربار یک yield return را شاهد خواهید بود که سربار مصرف حافظه‌ی بسیار کمی را دارد و برای کار با تعداد رکورد بالا بسیار مناسب است.
- برای بررسی دقیق‌تر این موارد همیشه از یک پروفایلر استفاده کنید؛ مانند DNTProfiler و برای مثال بررسی کنید که چه تعدادی کوئری SQL تولید شده. 
‫۵ سال و ۱ ماه قبل، پنجشنبه ۱۰ مرداد ۱۳۹۸، ساعت ۱۲:۴۷
از زمان ارائه‌ی NET Core 3 Preview 7. به بعد، امکان تعریف یک چنین اکشن متدهایی در ASP.NET Core وجود دارد:
[HttpGet]
public IAsyncEnumerable<Product> Get()
    => productsRepository.GetAllProducts();
‫۵ سال و ۱ ماه قبل، سه‌شنبه ۸ مرداد ۱۳۹۸، ساعت ۰۴:۵۹
- runAt را طوری تنظیم کنید که در طی یک بازه زمانی کار کند.
- و یا سرویس IOptions<ScheduledTasksStorage> storage را به قسمتی از برنامه‌ی خودتان تزریق کرده و از متد RemoveScheduledTask آن استفاده کنید.
‫۵ سال و ۱ ماه قبل، دوشنبه ۷ مرداد ۱۳۹۸، ساعت ۰۳:۴۲
به نحوه‌ی تعریف آن وظیفه و خصوصا بازه‌ی زمانی اجرای آن دقت کنید؛ برای مثال قسمت now.Day % 3 == 0 آن یعنی صرفا یکسری روزهای خاص اجرا شود، نه تمام روزها. بعد now.Hour == 0 && now.Minute == 1 && now.Second == 1 آن یعنی، در آن روزهای خاص، فقط در اولین دقیقه‌ی روز اجرا شود و نه هیچ وقت دیگری.