نظرات مطالب
Senior Developer به چه کسی گفته می شود؟
توضیح خوبی بود، ولی از بین تمام این مطالب این قسمت از نظر شما به دلم نشست:
در ضمن هنگام تهیه و مطالعه رزومه باید به عناوین تسلط و آشنایی و آگاهی دقت لازم را داشته باشیم. 
خیلی از افراد کفر آدم رو در می‌آرن، ردیف کرده کلی تخصص حتی بدون تفکیک و شاخه بندی. جالب اینه که در همه زمینه‌ها هم اصطلاح تسلط رو به کار برده. من خودم به شخصه تسلط بر یک مبحث رو خیلی اصطلاح سنگین و دشواری میبینم. چون واقعا برای شایسته این اصطلاح بودن باید در سطح آگاهی و آشنایی نباشیم، باید در سطحی باشیم که چندین و چند بار از این اطلاعات و آگاهی‌ها در عمل استفاده کرده باشیم. به نظر من کلاس‌های آموزشی و مطالعه کتاب و بسیاری از موارد دیگر تنها ما رو به سطح آشنایی می‌رسانند ولی بدون استفاده عملی و کاربردی از اطلاعات در همین سطح باقی میمونیم و به تسلط بر آن موضوع دست پیدا نمی‌کنیم.
با این تفاسیر متاسفانه کارفرمایان بین این واژه‌ها تفاوت چندانی قائل نمیشوند و بیشتر به اصطلاحات دهن پر کن توجه میکنند که البته در طولانی مدت هم با مشکل مواجه خواهند شد.
بگذارید با یک مثال ملموس این قضیه رو روشن کنم:
یادتون بیارید زمانی که تازه با کامپیوتر آشنا شدید، نصب نرم افزارهای کاربردی کوچک همیشه برای شما سورپرایزی داشته اند یعنی ممکنه برای نصب بعضی از نرم افزارها با مشکل مواجه شده باشید، شما در اینترنت و یا کتاب به دنبال راه حلی برای نصب آن نرم افزار بودید، تا اینجا در مرحله آگاهی قرار دارید، یعنی می‌دانید که نصب نرم افزار فرایندی بدون خطا نیست، شاید یه جاهایی با مشکل مواجه بشید که به راحتی نتونید حل کنید.
بعد از مدتی که این روند تکرار میشه آگاهی‌های شما تعمیم پیدا میکنه و به سطح آشنایی میرسه، دیگه نصب نرم افزار‌ها برای شما استرس و مشکلات پیش بینی نشده ای نداره. شما اکنون در مرحله آشنایی هستید.
الان در چه مرحله ای هستید؟ یقینا در سطح تسلط هستید، امکان نداره نصب مشکلترین نرم افزارها الان برای شما در بدترین حالت بیشتر از 1 ساعت طول بکشه. دیگه حتی به حدی رسیدید که دکمه Next‌و پذیرفتن لایسنز و محل نصب نرم افزار و ... جز روتین کار شده و مکثی روی این موارد ندارید.
شما الان می‌تونید بگید که من به نصب نرم افزارها تسلط کامل دارم.
آیا در زمینه Design pattern‌ها هم به همین صورت هستید؟ آیا در زمینه آزمایش واحد هم به همین صورت هستید؟ آیا استفاده از فلان الگوی طراحی به اندازه استفاده از حلقه For و کاربردش در ذهنتون قرار گرفته؟ آیا به اندازه با الگوی‌های طراحی کار کردید که در موقعیت‌های خاص ناخوداگاه به یاد استفاده از فلان الگوی طراحی بیفتید؟
اگر پاسخ این سولات مثبته شما واقعا به الگوی‌های طراحی مسلط هستید؟
اگر نیاز به کمی مکث و آزمون و خطا دارید، شما به الگوی‌های طراحی آشنا هستید؟
اگر فقط می‌دونید که برای فلان مسئله الگوی طراحی کاربرد داره و بتونید فلان کد رو که از الگوی طراحی استفاده کرده تا حدودی تحلیل کنید،‌شما به الگوی‌های طراحی آگاهی دارید.

پس به قول آقای پاکدل بین این سه مفهوم لطفا تفاوت قائل بشید.
مطالب
ممنوعیت استفاده از کوکی‌های ثالث توسط مرورگرها و تاثیر آن بر روی اعتبارسنجی برنامه‌ها

کوکی‌ها به اندازه‌ی خود اینترنت قدیمی هستند و تا سال‌ها، تنها گزینه‌ی شخصی سازی تجربه‌ی کاربری در وب و انتقال آن از یک صفحه به صفحه‌ی دیگری به‌شمار می‌آمدند؛ به این نوع کوکی‌ها، First-party cookies هم می‌گویند و توسط خود سایت ارائه دهنده‌ی محتوا و برنامه‌ها، تنظیم می‌شوند. در مقابل آن، third-party cookies یا کوکی‌های ثالث هم وجود دارند که از طریق دومین دیگری بجز دومین اصلی برنامه، ارائه و تنظیم می‌شوند؛ به همین جهت به آن‌ها Cross-site cookies هم می‌گویند. یکی از اهداف کوکی‌های ثالث، ردیابی فعالیت کاربران در بین سایت‌های مختلف است و این روزها به علت سوء استفاده‌های زیادی که از آن‌ها می‌شوند،‌ یکی از وسایل به اشتراک‌گذاری و جمع آوری اطلاعات خصوصی کاربران شده‌اند.

البته کوکی‌های ثالث، کاربردهای مفیدی هم دارند؛ مانند امکان پیاده سازی لاگین و اعتبارسنجی یکپارچه‌ی بین چندین برنامه که به آن SSO یا Single Sign On هم گفته می‌شود؛ نمونه‌ی آن، استفاده از Identity server و یا OpenId dict در دنیای دات‌نت است.

اما ... در کل به علت مشکلات یاد شده، اکثر مرورگرها تصمیم به عدم پذیرش و پردازش آن‌ها گرفته‌اند. برای مثال مرورگر Safari سال‌ها است که اینگونه کوکی‌ها را بلاک می‌کند و یا مرورگر فایرفاکس، کوکی‌های ثالث ردیاب‌ها را بلاک می‌کند و ... مرورگر کروم نیز تصمیم گرفته‌است، تا پایان سال 2024، به این جمع محلق شود. هرچند اخیرا اعلام کرده‌اند، بجای اینکه مرورگر کروم، راسا این کار را انجام دهد، قرار است امکان انتخاب این گزینه به خود کاربر واگذار شود (چون ... خود گوگل از این نوع کوکی‌ها منتفع است!). البته این تصمیم، به‌نظر W3C خوش نیامده و اعلام کرده‌اند که این نوع کوکی‌ها باید بروند!

روش آزمایش برنامه‌ها برای بررسی تاثیر ممنوعیت کوکی‌های ثالث

برای اینکه پیش از موعد، امکان آزمایش برنامه‌ی خود را داشته باشید و بتوانید تاثیر ممنوعیت بکارگیری کوکی‌های ثالث را بررسی کنید، در مرورگر کروم به آدرس زیر مراجعه کرده:

chrome://flags/#test-third-party-cookie-phaseout

و سپس این گزینه را فعال کنید و یا روش دوم فعالسازی آن، اجرای مرورگر کروم با سوئیچ test-third-party-cookie-phaseout-- از طریق خط فرمان است.

کدام برنامه‌ها با ممنوعیت کوکی‌های ثالث مشکل پیدا می‌کنند؟

اگر برنامه‌ی SSO شما، مبتنی بر اعتبارسنجی یکپارچه‌ی از نوع implicit flow است، حتما مشکل پیدا می‌کنید. در این حالت بهتر است به نوع امن‌تر authorization flow + PKCE‌ مهاجرت کنید.

علت مسدود شدن نوع اعتبارسنجی و احراز هویت implicit flow که در برنامه‌های تک صفحه‌ای وب (SPA/single-page apps) مرسوم است، شباهت بسیار زیاد آن به کاری است که ردیاب‌های اینترنتی انجام می‌دهند. در این‌حالت، سایت‌های ثالث، یک iframe مخفی را در پشت صحنه، درون سایت جاری باز کرده و توسط آن شروع به استفاده‌ی از امکانات مرتبط با کوکی‌ها می‌کنند. این الگو دقیقا همان کاری است که توسط implicit flow هم انجام می‌شود. بنابراین مرورگری که کوکی‌های ثالث از این دست را مسدود می‌کند، قابلیت اعتبارسنجی یکپارچه‌ی برنامه‌های SPA را هم غیرفعال خواهد کرد.

مطالب
جلوگیری از دوباره اجرا شدن ناخواسته‌ی متدهای نامتقارن در Blazor

اینطور که در این مطلب عنوان شده، ماوس‌های قدیمی در اثر مشکلات سخت افزاری، می‌توانند به‌ازای هر کلیک کاربر، دو سیگنال کلیک، ظرف مدت کوتاهی (برای مثال 5 میلی ثانیه) تولید کنند. برنامه‌های مبتنی بر Blazor، توسط متدهای نامتقارن می‌توانند هردوی این سیگنال‌ها را دریافت کرده و بنابراین متد مربوطه در کسری از ثانیه دوبار اجرا خواهد شد.

برای رهایی از این مشکل می‌توان از کدی شبیه زیر بهره جست:

<button disabled="@_busy" Value="do-stuff" />
code{
private bool _busy = false;

public async Task Handler()
{
    if(_busy) return;
    _busy = true;
   try
   {
       // do your thing
   }
   finally
   {
       _busy = false;
   }
}
}

منطق آن ساده است؛ تا زمانی که اجرای متد، پایان نپذیرفته‌است، دکمه‌ی مربوطه غیرفعال می‌گردد، تا نتوان دوباره روی آن کلیک کرد.

اگر نمی‌خواهید به ازای هر کامپوننت، این کدهای تکراری را ایجاد کنید، می‌توانید کدهای فوق را در قالب یک کامپوننت مانند زیر ایجاد کنید (با نام دلخواه HandleValidSubmitForm.razor):

<EditForm Model="Model" OnValidSubmit="HandleValidSubmit">
    @ChildContent?.Invoke(context)
    <button disabled="@_busy">Submit</button>
</EditForm>

@code {
    private bool _busy;

    [Parameter]
    public object? Model { get; set; }

    [Parameter]
    public EventCallback<EditContext> OnValidSubmit { get; set; }

    [Parameter]
    public RenderFragment<EditContext>? ChildContent { get; set; }

    private async Task HandleValidSubmit(EditContext editContext)
    {
        if (_busy) return;

        _busy = true;

        try
        {
            await OnValidSubmit.InvokeAsync(editContext);
        }
        finally
        {
            _busy = false;
        }
    }
}

سپس می‌توانید در دیگر کامپوننت‌ها به شکل زیر از آن بهره ببرید.

<HandleValidSubmitForm Model="_customer" OnValidSubmit="HandleValidSubmit">
    <InputText @bind-Value="_customer.FirstName" />
    <InputText @bind-Value="_customer.LastName" />
</HandleValidSubmitForm>

@code {
    private Customer _customer = new Customer();

    private async Task HandleValidSubmit()
    {
        // do your thing
    }

    public class Customer
    {
        public string? FirstName { get; set; }
        public string? LastName { get; set; }
    }
}
مطالب
به روز رسانی قالب فایل‌های csproj پروژه‌های قدیمی
اگر شما هم مثل بنده در حال نگه‌داری از یک سیستم قدیمی می‌باشید، به احتمال زیاد همیشه با یک سری مسائل مثل آپدیت پکیج‌ها، اضافه کردن یا حذف کردن فایلی از پروژه، مدیریت وابستگی‌ها، خروجی گرفتن از یک پروژه کنسول و ... درگیر هستید؛ مسائلی که سال‌هاست با روی کار آمدن «دات نت کور» و پس از آن «دات نت ۵» حل شده‌است. این حجم از مشکلات به حدی بود که گاهاً کدنویسی را با مشکل مواجه می‌کرد و امروز تصمیم گرفتم این مشکل را برای پروژه شرکت حل کنم. ابتدا باید بگویم، یک نسخه‌ی پشتیبان از کد خود تهیه کنید؛ چرا که زیاد به آن رجوع خواهید داشت.

انجام این آپدیت از طریق دو نرم‌افزار  upgrade-assistant و try-convert قابل انجام است. بنده به شخصه از upgrade-assistant استفاده کردم چرا که به نظر به بلوغ بیشتری رسیده‌است. ابتدا با دستور زیر این نرم‌افزار را نصب کنید:
dotnet tool install -g upgrade-assistant
اگر پیغامی دریافت میکنید مبتنی بر این که این نرم‌افزار قبلاً نصب شده، با دستور زیر از به‌روز بودن آن اطمینان حاصل کنید:
dotnet tool update -g upgrade-assistant

توجه داشته باشید، نرم‌افزار upgrade-assistant برای ارتقاء پروژه‌ها به دات نت 5 و 6 طراحی شده‌اند. بنابراین ما فقط با سه مرحله‌ی اول سر و کار داریم:
  • Back up project
  • Convert project file to SDK style
  • Clean up NuGet package references 

حال یک terminal را باز کنید و به محل پروژه بروید و دستور زیر را اجرا کنید:
upgrade-assistant upgrade MyProject.csproj
در دستور بالا، کلمه‌ی MyProject را با نام پروژه‌ی خود جایگزین کنید. پس از اجرای این دستور، مراحل ۱ تا ۳ را که پیش‌تر در مورد آن توضیح داده شد، اجرا کنید. توجه داشته باشید که اگر solution شما از بیش از یک پروژه تشکیل شده، برای هر پروژه به‌طور جداگانه‌ای باید این عمل تکرار شود. حال اگر فایل csproj پروژه را ببینید، متوجه آن می‌شوید که پروژه به ساختار جدید درآمده است.
  • اگر پروژه از جنس Library باشد، فایل csproj را به شکل زیر درآورید: 
<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>net472</TargetFramework>
        <OutputType>Library</OutputType>
    </PropertyGroup>
.
.
.
</Project>

  • اگر پروژه از جنس Console باشد، فایل csproj را به شکل زیر درآورید:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<OutputType>Exe</OutputType>
<ApplicationIcon>logo.ico</ApplicationIcon>
<AppConfig>App.config</AppConfig>
</PropertyGroup>
.
.
.
</Project>

  • اگر پروژه از جنس Web باشد، فایل csproj را به شکل زیر درآورید. احتمالاً پیچیده‌ترین و سخت‌ترین فایل‌ها، متعلق به پروژه‌های وب باشد. اگر دقت کنید نوع SDK از نوع MSBuild.SDK.SystemWeb می‌باشد. نسخه این SDK ممکن است در زمانیکه شما در حال خواندن این مطلب می‌باشد آپدیت شده باشد و بهتر است قبل از استفاده، آخرین نسخه را از نیوگت برداشت کنید. (باید ذکر کنم که این hack کوچک را از یک comment  در issueهای گیت‌هاب پیدا کردم.)
<Project Sdk="MSBuild.SDK.SystemWeb/4.0.54">
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net472</TargetFramework>
<AppConfig>Web.config</AppConfig>
</PropertyGroup>
.
.
.
</Project>
مطالب
پیدا کردن منشاء خطا در برنامه با آنالیز فایل‌های Dump

هنگامیکه خطاهای غیر منتظره‌ای در برنامه‌ی مدیریت شده‌ی شما رخ می‌دهند، شما اطلاعات کمی را در مورد این مساله دارید. اگرچه شما می‌توانید تا حدودی جلوی این نوع خطاهای غیرمنتظره را با ابزارهای خطایابی و یا لاگر، رصد کنید ولی همیشه اینطور نیست؛ در این حال ذخیره، تجزیه و تحلیل Dump‌های حافظه، ممکن است آخرین گزینه برای شما باشد. خوشبختانه ویژوال استودیو، ابزاری عالی برای تجزیه و تحلیل Dump‌های حافظه است! در این مطلب به شما نشان می‌دهیم که چگونه Dump‌های حافظه را جمع آوری کرده و توسط ویژوال استودیو راه حل مشکلات درج شده‌ی در آن‌ها را پیدا کنید.

ابزارهایی وجود دارند که حافظه را مورد کاوش قرار داده و فعالیت‌هایی را که یک پروسس انجام می‌دهد، مانیتور می‌کنند. در حال حاضر ابزارهای مختلفی برای اینکار وجود دارند؛ از جمله Visual Studio ،ProcDump ،DebugDiag و WinDbg که ما در این پست از ProcDump استفاده می‌کنیم. 

برای شروع، من یک برنامه‌ی ساده را ایجاد کردم که شامل یک button است و با فشردن آن، یک خطای نامشخص اتفاق می‌افتد. برنامه را اجرا میکنیم. سپس به TaskManager رفته و آی‌دی پروسس برنامه را پیدا میکنیم: 

  

آیدی پروسس ما، 10896 می‌باشد.

ProcDump را دانلود کرده و آن‌را توسط CMD، به این صورت اجرا می‌کنیم تا تمامی فعالیت‌های پروسس موردنظر را زیرنظر بگیرد و فایل Dump ای را تولید کند:

 procdump.exe -ma -e 10896


حالا نوبت به کلیک بر روی Button، جهت ایجاد خطا می‌رسد. بر روی دکمه کلیک کرده و منتظر می‌شویم تا Dump، از حافظه جمع آوری و در سیستم تولید شود. عملیات با موفقیت انجام شده و فایل Dump در آدرس مشخص شده، ایجاد می‌شود. 

 

پیدا کردن منشاء خطا  

بعد از ایجاد فایل Dump، نوبت به پیدا کردن منشا خطا و رسیدن به کد موردنظر می‌رسد. ویژوال استودیو را باز کنید و فایل Dump را درون VS درگ/دراپ کنید. 

  

در پنجره‌ای که باز می‌شود، می‌توانید مشخصات کاملی از برنامه را مشاهده کنید. سمت راست، چند گزینه وجود دارند که با توجه به نوع برنامه (مدیریت شده یا محلی) و زبان برنامه نویسی، باید آن‌ها را انتخاب کنید. از آنجائیکه برنامه‌ی ما با زبان سی شارپ ایجاد شده، گزینه‌ی اول یعنی Debug with Managed only را انتخاب می‌کنیم.

بعد از انتخاب این گزینه، بلافاصله به کدی که باعث ایجاد خطا می‌شود، هدایت می‌شویم

 

کلام آخر اینکه سعی کنید تا حد ممکن، خودتان خطاها را مدیریت کنید و از ابزارهای خطایاب مانند AppCenter نیز استفاده کنید. اخیرا WPF و WinForm نیز به AppCenter اضافه شده‌اند. 

مطالب
بازسازی کد: جایگزینی داده با شیء (Replace data with object)
بازسازی کد جایگزینی داده با شیء، معمولا در طراحی موجودیت‌های قابل ذخیره و بازیابی سیستم‌های اطلاعاتی مورد نیاز قرار می‌گیرید. این بازسازی کد معمولا زمانی مورد نیاز است که آیتم داده‌ای نیاز به اطلاعات بیشتر یا رفتاری خاص دارد. در این صورت باید آن آیتم داده‌ای را به شیء از کلاس یا ساختار (struct) تبدیل کرد. 
معمولا زمانیکه توسعه محصول انجام می‌گیرد، ممکن است آیتم‌های داده‌ای در ابتدا ساده دیده شوند و طراحی ساده‌ای برای آنها در نظر گرفته شود. به طور مثال در یک سیستم فرضی رسیدگی به تیکت، ممکن است با اقلام اطلاعاتی مانند آیتم‌های زیر روبرو باشیم:  
  •  شماره تلفن، به صورت رشته کاراکتری 
  • آدرس، به عنوان رشته کاراکتری 
  • نام مسئول رسیدگی به تیکت، به صورت رشته کاراکتری  
با توجه به مثال بالا، در طراحی اولیه AgentName، فیلدی از نوع رشته کاراکتری برای نگهداری نام مسئول رسیدگی به تیکت در نظر گرفته شده است (فرض می‌کنیم در این طراحی موضوعات مربوط به نرمال سازی پایگاه‌های داده را در نظر نگرفته‌ایم و تکرار شدن نام مسئول رسیدگی به تیکت اشکالی نداشته‌است). کلاس زیر نشان دهنده چنین طراحی‌ای است.  

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

در چنین شرایطی، یک اقدام ممکن، افزودن اقلام اطلاعاتی مورد نیاز در همان مکان آیتم قبلی است؛ به طور مثال اگر نام مسئول بر روی موجودیت تیکت باشد، شماره تلفن مسئول نیز در همان موجودیت تیکت اضافه شود.  

راه حل مناسب‌تر برای حل این نوع مشکلات ایجاد کلاس خاص آیتم اطلاعاتی و استفاده از شیء آن به‌جای مقدار مربوطه است. به طور مثال به طراحی زیر دقت نمایید.  در طراحی زیر کلاس دیگری به نام Agent ایجاد و در کلاس تیکت از آن استفاده کرده‌ایم.  

این بازسازی کد دو مزیت کلی دارد:  

  • راه را برای توسعه آینده آیتم‌های داده‌ای باز می‌کند
  • از تکرار آیتم‌های داده‌ای جلوگیری می‌کند (به طور مثال زمانیکه از پایگاه داده‌های رابطه‌ای جهت ذخیره سازی، استفاده شود)  
در مثال بالا علارغم اینکه قادر بودیم آیتم اطلاعاتی مسئول رسیدگی را به صورت ساختار (struct) تعریف کنیم، این آیتم اطلاعاتی را به صورت کلاس تعریف کردیم. تعریف به صورت کلاس امکان استفاده از رفرنس را به‌جای مقدار شیء، به ما خواهد داد. در اکثر بازسازی‌های کد، استفاده از کلاس‌ها مزیت‌های بیشتری نسبت به استفاده از ساختار دارد. برای مطالعه بیشتر در این مورد می‌توانید به اینجا مراجعه نمایید.  
مطالب
غیرمعتبر شدن کوکی‌های برنامه‌های ASP.NET Core هاست شده‌ی در IIS پس از ری‌استارت آن
ASP.NET Core از مکانیزم «Data protection» برای تولید کلیدهای رمزنگاری اطلاعات موقتی خود استفاده می‌کند. این روش در دو حالت هاست برنامه‌ها توسط IIS و یا عدم تنظیمات ذخیره سازی آن‌ها به صورت دائمی، اطلاعات خود را در حافظه نگه‌داری می‌کند و با ری‌استارت شدن سرور و یا IIS، این کلیدها از دست رفته و مجددا تولید می‌شوند. به این ترتیب کاربران شاهد این مشکلات خواهند بود:
الف) چون کوکی‌ها و یا توکن‌های آن‌ها دیگر قابل رمزگشایی نیستند (به علت باز تولید کلیدهای رمزنگاری و رمزگشایی اطلاعات)، مجبور به لاگین مجدد خواهند شد (تا کوکی‌های جدیدی برای آن‌ها تولید شوند). همچنین آنتی‌فورجری توکن‌های آن‌ها نیز مجددا باید تولید شوند.
ب) تمام اطلاعات محافظت شده‌ی توسط Data protection API قابل رمزگشایی نخواهند بود.


تنظیم Data protection API مخصوص برنامه‌های هاست شده‌ی توسط IIS

برای اینکه کلیدهای رمزنگاری اطلاعات برنامه‌های وب به صورت دائمی ذخیره شوند و با ری‌استارت سرور از دست نروند، یکی از سه روش ذیل را می‌توان بکار گرفت:

1) اسکریپت پاور شل ذیل را اجرا کنید:
نحوه‌ی اجرای آن نیز به صورت ذیل است و پس از آن، نام Application pool مخصوص برنامه ذکر می‌شود:
 .\Provision-AutoGenKeys.ps1 DefaultAppPool
در این حالت کلیدهای رمزنگاری اطلاعات به صورت دائمی به رجیستری ویندوز اضافه می‌شوند. این کلیدها به صورت خودکار توسط مکانیزم DPAPI ویندوز، رمزنگاری می‌شوند.

2) به تنظیمات پیشرفته‌ی Application pool برنامه در IIS مراجعه کرده و خاصیت Load user profile آن‌را true کنید.


در این حالت کلیدها به صورت دائمی در پوشه‌ی پروفایل کاربر مخصوص Application pool برنامه، به صورت رمزنگاری شده‌ی توسط مکانیزم DPAPI ویندوز، ذخیره خواهند شد.

3) یک SSL Certificate معتبر را تهیه کنید و یا اگر از یک self signed certificate استفاده می‌کنید باید آن‌‌را در Trusted Root store ویندوز قرار دهید. سپس از روش PersistKeysToFileSystem استفاده کنید.
public void ConfigureServices(IServiceCollection services)
{
   services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
    .ProtectKeysWithCertificate("thumbprint");
}

اگر از یک web farm استفاده می‌کنید، روش سوم ذکر شده، تنها روشی است که از آن می‌توانید استفاده کنید. یک پوشه‌ی اشتراکی قابل دسترسی بین سرورها را ایجاد کنید که دربرگیرنده‌ی X509 certificate شما باشد. سپس این پوشه و مجوز موجود در آن‌را توسط روش فوق به برنامه معرفی کنید.
مطالب
آشنایی با معماری فیزیکی یک بانک اطلاعاتی
یکی از مهمترین مسائلی که به مدیر پایگاه داده، در پیاده سازی صحیح و نگهداری و برطرف سازی مشکلات می‌تواند کمک کند، شناخت و درک مفاهیم صحیحی از معماری فیزیکی یک بانک اطلاعاتی است. در این مقاله قصد دارم به معرفی برخی از این موارد بپردازم.

1:data pages اساسی‌ترین واحد نگهداری داده در اس کیوال سرور، صفحه نام دارد. فضای دیسک اختصاص یافته به فایل داده بانک، برای یک بانک اطلاعاتی به صورت منطقی به صفحات پیوسته از صفر تا n تقسیم بندی می‌شود. همچنین لازم به ذکر است عملیات خواندن و یا نوشتن در دیسک، در سطح این صفحه‌ها صورت می‌گیرد که در تصویر زیر قابل مشاهده است:


 لازم به ذکر است در sql server هر صفحه، 8 کیلوبایت است. این مورد به این معنی است که هر بانک اطلاعاتی، دارای 128 صفحه به ازای هر یک مگابایت است. هر صفحه دارای 96 بایت با عنوان header یا سرصفحه است که شامل اطلاعات سیستمی در مورد صفحه است. این اطلاعات سیستمی شامل مواردی چون page number یا شماره صفحه و نوع صفحه یا page type و مقدار فضای خالی آن صفحه و شماره شناسایی یک واحد اختصاص یافته یا به اختصار allocation unit id و.... هستند می‌باشد. نکته جالب و قابل توجه این است که فایل‌های ثبت وقایع یا Log files از صفحه استفاده نمی‌کنند؛ بلکه شامل یکسری رکورد log هستند.
 برای بدست آوردن اطلاعات در مورد فایلهای دیتابیس می‌توانید از کد زیر استفاده نمایید SELECT * FROM sys.database_files که خروجی زیر را به شما نشان می‌دهد:


 extents: به ابتدایی‌ترین قسمتی که sql server امکان مدیریت بر آن را دارد extent گویند. هر extent شامل 8 صفحه‌ی به هم پیوسته است. لازم به ذکر است که sql server هر 1 مگابایت را به شانزده extent اختصاص می‌دهد. sql server شامل دونوع extent است که عبارتند از : uniform,mixed uniform extent متعلق به یک شیء است و هر هشت صفحه‌ی آن فقط توسط یک شیء قابل استفاده‌است. mixed extent می‌تواند حداکثر بین هشت شیء به اشتراک گذاشته شود؛ به نحوی که هر یک از هشت صفحه می‌توانند متعلق به یک شیء باشند. همانطور که در شکل زیر می‌بینید به طور پیش فرض با ایجاد یک جدول، یک mixed extent به آن اختصاص داده می‌شود. در صورتیکه این شیء به اندازه‌ی هشت صفحه رشد کند، به آن یک uniform extent اختصاص داده میشود.


فایلهای بانک اطلاعاتی
هر بانک اطلاعاتی در sql server دارای سه نوع فایل است
فایلهای داده اولیه یا به اختصار primary data files
فایلهای داده‌های ثانویه یا به اختصار secondary data files
فایلهای ثبت وقایع یا به اختصار log file
فایل ثبت وقایع برای نگهداری و ثبت وقایع که برای عملیات recovery مورد نیاز است. معمولا یک بانک اطلاعاتی یک log file دارد؛ ولی می‌تواند بیشتر هم داشته باشد. پسوند این نوع فایلها ldf است .

مطالب
کار با شاخه‌ها و انشعابات Git در Visual Studio
در مطلب «آشنایی با ساختار یک Pull Request خوب» عنوان شد که قابلیت‌های جدید و یا رفع مشکلات را در شاخه‌ی اصلی کار نکنید. اما ... چگونه؟


ایجاد یک شاخه‌ی جدید در Visual Studio و انتشار آن

به برگه‌ی Team explorer مراجعه کرده و سپس گزینه‌ی Branches آن‌را انتخاب کنید:


در برگه‌ی باز شده، انشعاب و شاخه‌ی جاری با فونت ضخیم نمایش داده می‌شود. برای مثال در اینجا، انشعاب کاری همان master است:


برای ایجاد یک شاخه‌ی جدید، بر روی لینک new branch کلیک کنید تا بتوان نامی را برای این منظور وارد کرد. بهتر است از نام‌های با مفهومی مانند feature-X و یا fix-Y استفاده کنید (افزودن قابلیت X و یا رفع مشکل Y) و در آخر بر روی دکمه‌ی Create branch کلیک کنید.
در اینجا می‌توان مشخص کرد که انشعاب ایجاد شده باید بر اساس کدام انشعاب فعلی نیز تهیه شود (دراپ داون ذیل قسمتی که می‌توان نام انشعاب را وارد کرد). برای مثال پروژه‌‌های مایکروسافت در GitHub، دارای سه شاخه‌ی master، dev و release هستند. شاخه‌ی dev (یا توسعه) جایی است که انشعابات pull requests را قبول خواهند کرد. بنابراین بر اساس ساختار و طراحی پروژه‌ی جاری به این موضوع نیز باید دقت داشت.

پس از ایجاد شاخه‌ی جدید، تصویر ذیل نمایان خواهد شد:


همانطور که ملاحظه می‌کنید، اینبار شاخه‌ی جدید ایجاد شده به صورت bold و ضخیم نمایش داده شده‌است. این bold بودن به معنای شاخه‌ی کاری جاری بودن است. همچنین این شاخه در قسمت unpublished branches قرار دارد. بنابراین کلیه‌ی تغییرات واقع شده‌ی در آن، محلی بوده و هنوز با سرور هماهنگ نشده‌اند.

برای انتشار و publish این شاخه، تنها کافی است تا بر روی آن کلیک راست کرده و گزینه‌ی publish branch را انتخاب کنیم:



این انتشار سبب نمایش لیستی از تغییرات جدید در برگه‌ی branches پروژه، در GitHub خواهد شد:



یک نکته: برای تغییر branch فعال جاری، فقط کافی است در برگه‌ی branches در ویژوال استودیو، دوبار بر روی لینک نام آن شاخه کلیک کنید تا به صورت bold ظاهر شود.


ارسال تغییرات انجام شده‌ی در Branch به سرور

پس از کار بر روی شاخه‌ی جدید ایجاد شده، اکنون نوبت به ارسال و هماهنگ سازی این تغییرات با سرور است. این مورد نیز همانند قبل بوده و ابتدا باید به برگه‌ی Home و گزینه‌ی changes آن مراجعه کرد:



و سپس تغییرات را به همراه توضیحی commit کرد:




اینکار سبب sync محلی می‌شود. سپس بر روی لینک sync کلیک نمائید و تغییرات را با سرور هماهنگ کنید.







یکی کردن تغییرات شاخه‌ی جدید با شاخه‌ی اصلی

هرچند این تغییرات به سرور ارسال شده‌اند، اما چون در یک انشعاب کاری دیگر قرار دارند، با انشعاب اصلی یکی نخواهند شد. برای انجام عملیات merge، ابتدا به برگه‌ی Home و سپس گزینه‌ی branches مراجعه کنید. در ادامه بر روی لینک merge کلیک نمائید (تصاویر اول و دوم بحث).



در اینجا می‌خواهیم اطلاعات موجود در شاخه‌ی افزودن توضیحات را با شاخه‌ی اصلی یکی کنیم (انتخاب منبع و مقصد). سپس بر روی دکمه‌ی merge کلیک نمائید.
اکنون برای ارسال این تغییرات به سرور، به برگه‌ی Home و سپس گزینه‌ی unsynced commits مراجعه کرده و بر روی دکمه‌ی sync کلیک نمائید تا تغییرات یکی شده به سرور ارسال شوند.

مطالب
BulkInsert در EF CodeFirst
یکی از مشکلات برنامه نویسان، نوشتن هزاران رکورد در دیتابیس در مدت زمان بسیار کوتاهی است که عموما این کار در هنگام خواندن اطلاعات از فایل‌های اکسل و گاها از فایل‌های text ای اتفاق می‌افتد. برای مثال در زمان نوشتن این اطلاعات، با Timeout مواجه شده و اگر هم Timeout ندهد بسیار کند عمل می‌کند.
در این پست قصد داریم روش نوشتن هزاران رکورد را در کسری از ثانیه توسط EF Code first مورد بررسی قرار دهیم و در نهایت مقایسه ای با AddRange در EntityFramework داشته باشیم.
خوب؛ در ابتدا مدلی را با نام Personel را به شکل زیر طراحی مینماییم .
public class Personel
    {
        [Key]
        public int PersonelID { get; set; }

        [MaxLength(15)]
        public string Name { get; set; }

        [MaxLength(25)]
        public string Family { get; set; }

        [MaxLength(10)]
        public string CodeMelli { get; set; }

    }
 سپس این مدل را در Context خود معرفی نمایید همانند کلاس زیر:
 public class PersonalContext : DbContext
    {
        public DbSet<Personel> Personel { get; set; }
       
        public override int SaveChanges()
        {
            return base.SaveChanges();
        }
    }
برای ساختن دیتابیس در Entityframework CodeFirst  میتوانید به سری آموزشی CodeFirst در سایت جاری مراجعه نمایید. اکنون همه چیز مهیا است برای انجام عملیات Bulk Insert .
در ابتدا پاورشل نیوگت را باز کرده و پکیج مورد نظر را با توجه به نسخه Ef استفاده شده، به پروژه اضافه نمایید. همانند دستور زیر :
Install-Package EntityFramework.BulkInsert-ef6
بعد از نصب پکیج مورد نظر، باید لیستی از موجودیت‌ها را از یک فایل اکسل خوانده و به BulkInsert EF ارسال نماییم. برای این کار مانند زیر عمل مینماییم.
public ActionResult Insert()
        {
            int Counter = 1000;
            List<Personel> Lst = new List<Personel>();
            // شبیه سازی خواندن رکورد‌ها از فایل اکسل
            for (int i = 0; i < Counter; i++)
            {
                Lst.Add(new Personel
                {
                    CodeMelli = "0000000000",
                    Family = "Karimi",
                    Name = "Mohammad"
                });
            }

            PersonalContext db = new PersonalContext();
            db.BulkInsert(Lst);
            db.SaveChanges();
            return View();
        }
تنها نکته‌ی استفاده از متد BulkInsert، اضافه نمودن ارجاعی از ;using EntityFramework.BulkInsert.Extensions به بالای کلاس جاری است.
در شکل زیر  میتوانید مقایسه ای بین bulkInsert  و AddRange را در تعداد رکورد‌های نوشته شده و مدت زمان صرف شده برای نوشتن در دیتابیس، مشاهده نمایید.