نظرات مطالب
شبیه سازی outer Join در entity framework
جهت تکمیل بحث، اگر مدل‌های برنامه به این صورت باشند (محل تولد اجباری است و Id کلید خارجی آن نال پذیر نیست؛ به همراه محل صدور اختیاری، که Id نال پذیر دارد):
    public class Place
    {
        public int Id { set; get; }
        public string Name { set; get; }

        public virtual ICollection<Person> Personnel { set; get; }
    }

    public class Person
    {
        public int Id { set; get; }
        public string FirstName { set; get; }
        public string LastName { set; get; }

        [ForeignKey("BirthPlaceId")]
        public virtual Place BirthPlace { set; get; }
        public int BirthPlaceId { set; get; }

        [ForeignKey("IssuanceLocationId")]
        public virtual Place IssuanceLocation { set; get; }
        public int? IssuanceLocationId { set; get; }
    }
با این Context :
public class MyContext : DbContext
    {
        public DbSet<Place> Places { get; set; }
        public DbSet<Person> Personnel { get; set; }

        public MyContext()
        {
            this.Database.Log = sql => Console.WriteLine(sql);
        }
    }
آنگاه خروجی کوئری ذیل (که یک include دارد روی خاصیت راهبری که مقدار Id کلید خارجی آن ممکن است نال باشد (محل صدور) و نه مورد دومی که Id غیرنال پذیر دارد (محل تولد))
context.Personnel.Include(x => x.IssuanceLocation)
معادل خواهد بود با (left outer join به صورت خودکار تشکیل شده)
SELECT
    [Extent1].[Id] AS [Id],
    [Extent1].[FirstName] AS [FirstName],
    [Extent1].[LastName] AS [LastName],
    [Extent1].[BirthPlaceId] AS [BirthPlaceId],
    [Extent1].[IssuanceLocationId] AS [IssuanceLocationId],
    [Extent2].[Id] AS [Id1],
    [Extent2].[Name] AS [Name],
    [Extent1].[Place_Id] AS [Place_Id]
    FROM  [dbo].[People] AS [Extent1]
    LEFT OUTER JOIN [dbo].[Places] AS [Extent2] ON [Extent1].[IssuanceLocationId] = [Extent2].[Id]

و خروجی کوئری زیر که DefaultIfEmpty را هم لحاظ کرده و join نویسی صریحی هم دارد (مطابق مقاله فوق):
var query = from personnel in context.Personnel
                            join issuanceLocation in context.Places on
                                  personnel.IssuanceLocationId equals issuanceLocation.Id into aIssuanceLocation
                            from IL in aIssuanceLocation.DefaultIfEmpty()
                            join birthLocation in context.Places on
                                  personnel.BirthPlaceId equals birthLocation.Id into aBirthLocation
                            from BL in aBirthLocation.DefaultIfEmpty()
                            select new
                               {
                                   personnel.Id,
                                   personnel.FirstName,
                                   personnel.LastName,
                                   IssuanceLocation = IL.Name,
                                   BirthLocation = BL.Name
                               };
معادل است با:
SELECT
                        [Extent1].[Id] AS [Id],
                        [Extent1].[FirstName] AS [FirstName],
                        [Extent1].[LastName] AS [LastName],
                        [Extent2].[Name] AS [Name],
                        [Extent3].[Name] AS [Name1]
                        FROM [dbo].[People] AS [Extent1]
                        LEFT OUTER JOIN [dbo].[Places] AS [Extent2] ON [Extent1].[IssuanceLocationId] = [Extent2].[Id]
                        INNER JOIN [dbo].[Places] AS [Extent3] ON [Extent1].[BirthPlaceId] = [Extent3].[Id]
و البته این خروجی دوم فقط در صورتی تشکیل می‌شود که قسمت select new ذکر شود. در غیراینصورت مشکل select n+1 را پیدا می‌کند و اصلا چنین join ایی تشکیل نخواهد شد (در یک حلقه، به ازای هر شخص، یکبار کوئری select به جدول مکان‌ها تشکیل می‌شود). همچنین یک inner join هم علاوه بر left outer join تشکیل شده (برای فیلد غیرنال پذیر).
حتی همین حالت دوم را هم با کوئری ذیل که از خواص راهبری استفاده کرده، می‌توان تولید کرد:
var query = context.Personnel.Select(x => new
             {
              x.Id,
              x.FirstName,
              x.LastName,
              BirthPlaceName = x.BirthPlace.Name,
              IssuanceLocationName = x.IssuanceLocation == null ? "" : x.IssuanceLocation.Name
             });
با این خروجی SQL (به صورت خودکار برای فیلد نال پذیر، left outer join و برای غیر نال پذیر inner join تشکیل داده)
SELECT
    [Extent1].[Id] AS [Id],
    [Extent1].[FirstName] AS [FirstName],
    [Extent1].[LastName] AS [LastName],
    [Extent2].[Name] AS [Name],
    CASE WHEN ([Extent3].[Id] IS NULL) THEN N'' ELSE [Extent3].[Name] END AS [C1]
    FROM   [dbo].[People] AS [Extent1]
    INNER JOIN [dbo].[Places] AS [Extent2] ON [Extent1].[BirthPlaceId] = [Extent2].[Id]
    LEFT OUTER JOIN [dbo].[Places] AS [Extent3] ON [Extent1].[IssuanceLocationId] = [Extent3].[Id]
اشتراک‌ها
gRPC + ASP.NET Core به عنوان جایگزینی برای WCF در NET Core.

gRPC + ASP.NET Core as a Migration Path for WCFs in .NET Core 

Feature WCF ASP.Net Core + gRPC
Platforms Windows Windows, Linux, MacOS
Protocols LRPC/Named Pipes/HTTP/TCP/MSMQ Binary (GRPC) + HTTP2

(TCP/Named Pipes/LRPC)

.AddProtocol(“ncacn_ip_tcp”, “8080”)

.AddProtocol(“ncacn_np”, @”\pipe\MyService”)

.AddProtocol(“ncalrpc”, “MyService”)

By removing the ASP.NET Core stack and just using .NET Core

Injected Aspects Behaviors ASP.NET Core DI Middleware/ gRPC interceptors
Distributed Transactions *Yes – [TransactionFlow], transactionscopes, and supported bindings *No
Transport Security SSL/TLS SSL/TLS
Message Security Certificates/credentials Certificates/credentials

https://docs.microsoft.com/en-us/aspnet/core/grpc/authn-and-authz?view=aspnetcore-3.0

Windows Authentication Kerberos/NTLM AAD Sync/ASFS + ASP.NET Core middleware
Proxies/Contracts Service Contracts/Data Contracts Protocol Buffers
Proxy-less Communication WCF Channel Factory † Protobuf-Net.GRPC
gRPC + ASP.NET Core به عنوان جایگزینی برای WCF در NET Core.
بازخوردهای دوره
مدیریت استثناءها در حین استفاده از واژه‌های کلیدی async و await
همانطور که در بالا اشاره کردید "در مثال فوق، نحوه‌ی ترکیب دو Task را توسط Task.WhenAll .... "در برخی موارد استفاده از async باعث افزایش کارآیی نیز می‌شود، آیا در موردی که مثلا من در یک اکشن برای انجام کاری نیاز به 4 درخواست  مجزا به دیتابیس دارم و بعد از گرفتن نتیجه این 4 درخواست می‌توانم درخواست نهایی را به دیتابیس بفرستم، استفاده از async باعث افزایش کارایی نیز می‌شود ؟
برای تشریح بهتر من نتیجه تست خود را اضافه میکنم. من از mvc5 و EF6  database first استفاده کردم.
حالت sync :
var watch = Stopwatch.StartNew();

 int actionId = db.CF_AccessLevel.Where(a => a.Name.ToLower().Trim() == "Edit").Select(a => a.CF_AccessLevelId).Single();

 int moduleItemId = db.CF_ModuleItem.Where(m => m.Title.ToLower().Trim() == "license".ToLower().Trim()).Select(m => m.CF_ModuleItemId).Single();

 int groupRoleId = db.Users.Where(u => u.UserId == 1).Select(u => u.UserRoleId).Single();

watch.Stop();
 var elapsedMs = watch.ElapsedMilliseconds;

حالت async:
var watch = Stopwatch.StartNew();
 var something = Task<int>.Factory.StartNew(() => db.CF_AccessLevel.Where(a => a.Name.ToLower().Trim() == "Edit").Select(a => a.CF_AccessLevelId).Single());
something.Wait();
int actionId = something.Result;

var something1 = Task<int>.Factory.StartNew(() => db.CF_ModuleItem.Where(m => m.Title.ToLower().Trim() == "license".ToLower().Trim()).Select(m => m.CF_ModuleItemId).Single());
 something1.Wait();
 int moduleItemId = something1.Result;

var something2 = Task<int>.Factory.StartNew(() => db.Users.Where(u => u.UserId == 1).Select(u => u.UserRoleId).Single());
 something2.Wait();
 int groupRoleId = something2.Result;
 watch.Stop();
 var elapsedMs = watch.ElapsedMilliseconds;
در هر  حالت بعد از انجام  3 درخواست ، درخواست نهایی را به سرور میفرستم (در کدهای بالا موجود نیست)
و نتیجه با جزئیات را در آخر اضافه کرده ام :
اما خلاصه میانگین روش sync 222 ms و روش async 191.75ms می‌باشد حدود 35.25ms تفات وجود دارد.
حال آیا تفاوت معنی دار می‌باشد؟ آیا کد async نوشته شده صحیح است؟ اگر صحیح نیست چه روشی صحیح میباشد؟ اگر نباید از async استفاده شود چه روشی بهتر است؟
همانطور که از کد مشخص است برای هدف authorization  نوشتم، ولی اگر بخواهم به صورت async در فیلتر استفاده کنم امکانپذیر نیست ، آیا راهی وجود دارد برای استفاده از async در فیلتر سفارشی توی    mvc5 ؟
202  221
 179 226
 198 208
 197  219
 188  245
 195  207
 193  217
 187  220
 171  212
 227  215
 177  312
 187  222
 191.75  227
   
اشتراک‌ها
افزونه سی شارپ vscode به زودی از Razor پشتیبانی می کند.

As discussed previously, this adds Razor support behind a new omnisharp.preview options flag. It works by downloading a platform-specific Razor Language Server executable (equivalent to the OmniSharp-Roslyn language server) and then running some VSCode-side logic that knows how to launch and interact with it. 

افزونه سی شارپ vscode به زودی از Razor پشتیبانی می کند.
نظرات مطالب
Blazor 5x - قسمت 34 - توزیع برنامه‌های Blazor بر روی IIS
یه پروژه  Blazor WebAssembly App با NET 7. ایجاد کردم، بدون تغییر تنظیماتی publish گرفتم و روی سرور قرار دادم اما به درستی لود نمیشه و خطا میده، راه حلی براش پیدا نکردم
لود محتوای صفحه تا 93% میره و این خطا رخ میده

نظرات مطالب
Blazor 5x - قسمت 27 - برنامه‌ی Blazor WASM - کار با سرویس‌های Web API
یک نکته: تاثیر hot reload دات نت 6 بر روی درخواست‌های HTTP سمت کلاینت

ممکن است پس از ارتقاء به دات نت 6، شاهد خطاهای BadHttpRequestException زیادی در سمت Web API شوید (البته فقط در حالت توسعه):
Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException: Unexpected end of request content.
این خطا عنوان می‌کند که درخواست HTTP رسیده ناقص است و در اینجا بیشتر به معنای abort شدن آن در سمت کلاینت است. عکس العمل برنامه‌ی Blazor به یک چنین خطایی که در سمت سرور رخ داده، ریفرش کردن کل آدرس جاری و راه اندازی مجدد برنامه‌است. اما ... چرا این اتفاق رخ داده بود؟

اگر برنامه‌ی شما اطلاعاتی را در پوشه‌ی wwwroot ثبت کند، برای مثال یک بانک اطلاعاتی SQLite را در آن قرار داده‌اید، hot reload حتی این پوشه را هم تحت کنترل خود دارد و با هر تغییری در آن، حتی نوشته شدن یک رکورد در فایل بانک اطلاعاتی، مجددا برنامه را کامپایل می‌کند. همین کامپایل پشت صحنه، سبب abort شدن درخواست‌های HTTP سمت کلاینت آن و مشاهده‌ی خطاهای BadHttpRequestException سمت سرور می‌شود که عدم اطلاع از دلیل آن می‌تواند این تصور را پیش بیاورد که کدهای برنامه مشکلی دارند، اما خیر.
اگر با CLI کار می‌کنید، دستور dotnet watch run --no-hot-reload کمی وضع را بهتر می‌کند و معادل افزودن تنظیم زیر به فایل Properties\launchSettings.json است:
"profiles": {
  "Name.Server": {
      "hotReloadEnabled": false,
راه حل دیگر آن، خارج کردن پوشه‌ی wwwroot از حالت watch است که به صورت زیر در فایل csproj قابل انجام است (در سمت برنامه‌ی web api):
<ItemGroup>
  <Watch Remove="wwwroot\**\*" />
</ItemGroup>
اشتراک‌ها
مایکروسافت: NET Core. آینده‌ی NET. است

All future investment in .NET will be in .NET Core. This includes:  Runtime,   JIT , AOT,   GC,  BCL (Base Class Library),  C#, VB .NET , F#, ASP.NET,  Entity Framework ML.NET,  WinForms, WPF  and Xamarin.  

مایکروسافت: NET Core. آینده‌ی NET. است
نظرات مطالب
اندازه گیری کارآیی کدها توسط NBench
یک نکته‌ی تکمیلی
بجای NBench، این‌روزها BenchmarkDotNet تبدیل به استانداردی برای اندازه‌گیری کارآیی برنامه‌های دات نت شده‌است. چند نمونه مثال از کاربرد آن توسط تیم‌های مایکروسافت جهت اندازه‌گیری کارآیی قسمت‌های مختلف NET Core.: