مطالب
Minimal API's در دات نت 6 - قسمت اول - معرفی
یکی از مهم‌ترین تغییرات دات نت 6، ارائه‌ی Minimal API's به همراه آن است که نسبت به MVC و سایر مشتقات ASP.NET Core، کمتر به همراه پیش‌فرض‌های نظری خاص و بسیار مقید و متعصبانه (opinionated) است؛ که این مورد خود مزیتی است جهت انجام امور متداول، به نحوی دیگر و دلخواه و با آزادی عمل بیشتری در طراحی endpoints مورد نیاز و کل برنامه. خصوصا این سبک جدید، با معماری برش‌های عمودی (vertical slices) ارائه شده‌ی توسط نویسنده‌ی AutoMapper، هماهنگی خاصی دارد و اینطور به نظر می‌رسد که جهت ساده سازی طراحی برنامه‌های ASP.NET Core با معماری CQRS ارائه شده‌است. با وجود Minimal API's می‌توان از دو لایه‌ی متداول برنامه‌ها رها شد: لایه‌ی سرویس‌ها و لایه‌ی مخازن یا Repositories. در معماری برش‌های عمودی، برنامه به ویژگی‌های خاصی (Features) تقسیم شده و هر ویژگی، متکی به خود طراحی می‌شود. زمانیکه از هندلرها برای هر Command و Query معماری CQRS استفاده می‌کنیم، این‌ها مختص به یک ویژگی متکی به خود طراحی می‌شوند و به همراه تمام اطلاعات و اعمال مرتبط هستند و دیگر در این حالت، وجود لایه‌های سرویس و مخزن، بی‌معنا و غیرضروری می‌شوند.

در ادامه قصد داریم تمام این موارد را مانند Minimal API's و معماری برش‌های عمودی به همراه CQRS، در طی یک سری و یک پروژه‌ی عملی ساخت یک Blog به نام MinimalBlog، بررسی کنیم. البته هدف ما در اینجا صرفا ساخت backend ساختار یافته‌ی این برنامه‌است؛ منهای UI آن. هدف اصلی ما از این سری، ارائه‌ی یک معماری، جهت کار با Minimal API's است.


دریافت کدهای کامل این سری

جهت مرور سریعتر و ساده‌تر این سری، کدهای کامل آن‌را از اینجا می‌توانید دریافت کنید: MinimalBlog.zip


پروژه‌هایی که برنامه‌ی MinimalBlog را تشکیل می‌دهند

برنامه‌ی MinimalBlog، تنها از سه پروژه‌ی زیر تشکیل می‌شود:
MinimalBlog.Api: این پروژه از نوع minimal API's است که توسط دستور جدید «dotnet new webapi --use-minimal-apis» آغاز خواهد شد و به صورت پیش‌فرض به همراه پشتیبانی از OpenAPI نیز هست. البته اگر از VS2022 استفاده می‌کنید، در حین آغاز یک پروژه‌ی Web API جدید، تیک مربوط به use controllers را در UI بردارید تا از Minimal API's استفاده شود.
MinimalBlog.Dal: که Dal در اینجا مخفف data access layer است و یک class library می‌باشد و با دستور dotnet new classlib آغاز می‌شود.
MinimalBlog.Domain: نیز یک class library است و با دستور dotnet new classlib آغاز می‌شود.

همانطور که مشاهده می‌کنید، این طراحی جدید، بدون وجود لایه‌ی متداول سرویس‌ها و یا مخازن است.


بررسی ساختار ابتدایی پروژه‌ی MinimalBlog.Api

در اینجا تنها تک فایل Program.cs، به همراه تنظیمات برنامه قابل مشاهده‌است و فایل Starup.cs از آن حذف شده‌است (اطلاعات بیشتر). این فایل نیز بر مبنای مفهوم top level programs طراحی شده‌است و به همراه تعریف class و یا فضای نامی نیست:
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
همانطور که ملاحظه می‌کنید، تمام اتفاقات در همین تک فایل رخ می‌دهند. برای مثال سرویس‌های مورد نیاز برنامه به مجموعه‌ی builder.Services اضافه می‌شوند؛ شبیه به کاری که پیشتر در فایل Startup.cs و متد ConfigureServices آن انجام می‌دادیم.

پس از آن به تعاریف زیر می‌رسیم؛ تعاریف میان افزارهایی که پیشتر در متد Configure کلاس Startup انجام می‌شدند، الان همگی در تک فایل Program.cs قرار دارند:
var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
البته هنوز هم می‌توان در صورت نیاز به همان ساختار کلاس Startup پیشین نیز رسید.


در انتهای این فایل نیز تعاریف پیش‌فرض زیر قرار دارند:
var summaries = new[]
{
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

app.MapGet("/weatherforecast", () =>
{
    var forecast =  Enumerable.Range(1, 5).Select(index =>
        new WeatherForecast
        (
            DateTime.Now.AddDays(index),
            Random.Shared.Next(-20, 55),
            summaries[Random.Shared.Next(summaries.Length)]
        ))
        .ToArray();
    return forecast;
})
.WithName("GetWeatherForecast");

app.Run();

record WeatherForecast(DateTime Date, int TemperatureC, string? Summary)
{
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
در اینجا متد متد MapGet یک endpoint را تعریف کرده و سپس اکشنی را به آن انتساب می‌دهد. یعنی اگر آدرس weatherforecast/ درخواست شود، lambda expression تعریف شده، اجرا می‌شود. هدف از ارائه‌ی Minimal API نیز همین است تا بتوان با حداقل کدنویسی، سریعا به نتیجه‌ی مدنظر خود رسید.
در همین حال اگر برنامه‌ی Api را اجرا کنیم، به تصویر زیر خواهیم رسید:


در ادامه کدهای موجود در این فایل را Refactor کرده و به کلاس‌های دیگری منتقل می‌کنیم؛ چون اگر قرار باشد در طول زمان تمام endpoints مدنظر را در همینجا تعریف کنیم، کنترل برنامه از دست خارج خواهد شد.


غنی سازی Solution و کامپایلر #C با استفاده از فایل‌های editorconfig. و Directory.Build.props

در مورد این دو فایل در مطلب «غنی سازی کامپایلر C# 9.0 با افزونه‌ها » بیشتر بحث شده‌است. هدف از آن‌ها، اعمال یکسری تنظیمات سراسری، به تمام پروژه‌های یک solution به صورت یک‌دست است؛ مانند تنظیمات کامپایلر جهت نمایش اخطارها به صورت خطاها، تعریف usingهای سراسری سی‌شارپ 10 و یا اعمال Roslyn analyzers به تمام پروژه‌ها. این دو فایل را به همراه پروژه‌ی پیوست می‌توانید دریافت کنید و ... باید جزء استاندارد تمام پروژه‌های جدید باشند. چون وجود آن‌ها سبب خواهد شد که به شدت کیفیت کدهای نهایی افزایش یابند و مبتنی بر یکسری best practices شوند.
اشتراک‌ها
معرفی Zen Coding یا Emmet Syntax

معرفی Zen Coding یا Emmet Syntax

برای من همیشه نوشتن کد‌های HTML با دشواری و مرارت‌های زیادی همراه بوده. نوشتن ساختار‌های تو در تو، قرار دادن id و class مناسب و باز و بسته کردن تگ‌ها و قرار دادن قرزند‌ها در داخل تگ‌ها حقیقتا کار هایی خسته کننده، تکراری و حوصله سر بر هستند.
روش Zen Coding یا Emmet Syntax برای حل همین مسئله به وجود آمده و سرعت توسعه کد‌های HTML را بسیار بیشتر خواهد کرد. پس از استفاده از این روش، به هیچ وجه قادر نخواهید بود که به روش سنتیِ گذشته کد‌های HTML بزنید.
1. مثلا با استفاده از دستور div#control.panel.panel-success و فشردن کلید tab، یک div با شناسه panel و کلاس‌های panel و panel-success ساخته خواهد شد.
2. با استفاده از Zen Codding به راحتی می‌توانیم المنت‌های داخلی هم در یک خط تعریف کنیم. مثلا ul>li*5 موجب خواهد شد یک ul همراه با پنج المنت li در درون اش تعریف شود.
سعی کنید حتما از روش Zen Coding استفاده کنید، چرا که سرعت توسعه شما را به شدت بالا خواهد برد.
Zen Coding پس از نصب افزونه Web Essentials در ویژوال استودیو افزوده خواهد شد. همچنین Visual Studio Code به طور پیش فرض از این روش پشتیبانی می‌کند.
 

معرفی Zen Coding یا Emmet Syntax
مطالب
EF Code First #1

در ادامه بحث ASP.NET MVC می‌شود به ابزاری به نام MVC Scaffolding اشاره کرد. کار این ابزار که توسط یکی از اعضای تیم ASP.NET MVC به نام استیو اندرسون تهیه شده، تولید کدهای اولیه یک برنامه کامل ASP.NET MVC از روی مدل‌های شما می‌باشد. حجم بالایی از کدهای تکراری آغازین برنامه را می‌شود توسط این ابزار تولید و بعد سفارشی کرد. MVC Scaffolding حتی قابلیت تولید کد بر اساس الگوی Repository و یا نوشتن Unit tests مرتبط را نیز دارد. بدیهی است این ابزار جای یک برنامه نویس را نمی‌تواند پر کند اما کدهای آغازین یک سری کارهای متداول و تکراری را به خوبی می‌تواند پیاده سازی و ارائه دهد. زیر ساخت این ابزار، علاوه بر ASP.NET MVC، آشنایی با Entity framework code first است.
در طی سری ASP.NET MVC که در این سایت تا به اینجا مطالعه کردید من به شدت سعی کردم از ابزارگرایی پرهیز کنم. چون شخصی که نمی‌داند مسیریابی چیست، اطلاعات چگونه به یک کنترلر منتقل یا به یک View ارسال می‌شوند، قراردادهای پیش فرض فریم ورک چیست یا زیر ساخت امنیتی یا فیلترهای ASP.NET MVC کدامند، چطور می‌تواند از ابزار پیشرفته Code generator ایی استفاده کند، یا حتی در ادامه کدهای تولیدی آن‌را سفارشی سازی کند؟ بنابراین برای استفاده از این ابزار و درک کدهای تولیدی آن، نیاز به یک پیشنیاز دیگر هم وجود دارد: «Entity framework code first»
امسال دو کتاب خوب در این زمینه منتشر شده‌اند به نام‌های:
Programming Entity Framework: DbContext, ISBN: 978-1-449-31296-1
Programming Entity Framework: Code First, ISBN: 978-1-449-31294-7
که هر دو به صورت اختصاصی به مقوله EF Code first پرداخته‌اند.


در طی روزهای بعدی EF Code first را با هم مرور خواهیم کرد و البته این مرور مستقل است از نوع فناوری میزبان آن؛ می‌خواهد یک برنامه کنسول باشد یا WPF یا یک سرویس ویندوز NT و یا ... یک برنامه وب.
البته از دیدگاه مایکروسافت، M در MVC به معنای EF Code first است. به همین جهت MVC3 به صورت پیش فرض ارجاعی را به اسمبلی‌های آن دارد و یا حتی به روز رسانی که برای آن ارائه داده نیز در جهت تکمیل همین بحث است.


مروری سریع بر تاریخچه Entity framework code first

ویژوال استودیو 2010 و دات نت 4، به همراه EF 4.0 ارائه شدند. با این نگارش امکان استفاده از حالت‌های طراحی database first و model first مهیا است. پس از آن، به روز رسانی‌های EF خارج از نوبت و به صورت منظم، هر از چندگاهی ارائه می‌شوند و در زمان نگارش این مطلب، آخرین نگارش پایدار در دسترس آن 4.3.1 می‌باشد. از زمان EF 4.1 به بعد، نوع جدیدی از مدل سازی به نام Code first به این فریم ورک اضافه شد و در نگارش‌های بعدی آن، مباحث DB migration جهت ساده سازی تطابق اطلاعات مدل‌ها با بانک اطلاعاتی، اضافه گردیدند. در روش Code first، کار با طراحی کلاس‌ها که در اینجا مدل داده‌ها نامیده می‌شوند، شروع گردیده و سپس بر اساس این اطلاعات، تولید یک بانک اطلاعاتی جدید و یا استفاده از نمونه‌ای موجود میسر می‌گردد.
پیشتر در روش database first ابتدا یک بانک اطلاعاتی موجود، مهندسی معکوس می‌شد و از روی آن فایل XML ایی با پسوند EDMX تولید می‌گشت. سپس به کمک entity data model designer ویژوال استودیو، این فایل نمایش داده شده و یا امکان اعمال تغییرات بر روی آن میسر می‌شد. همچنین در روش دیگری به نام model first نیز کار از entity data model designer جهت طراحی موجودیت‌ها آغاز می‌گشت.
اما با روش Code first دیگر در ابتدای امر مدل فیزیکی و یک بانک اطلاعاتی وجود خارجی ندارد. در اینجا EF تعاریف کلاس‌های شما را بررسی کرده و بر اساس آن، اطلاعات نگاشت‌های خواص کلاس‌ها به جداول و فیلدهای بانک اطلاعاتی را تشکیل می‌دهد. البته عموما تعاریف ساده کلاس‌ها بر این منظور کافی نیستند. به همین جهت از یک سری متادیتا به نام ویژگی‌ها یا اصطلاحا data annotations مهیا در فضای نام System.ComponentModel.DataAnnotations برای افزودن اطلاعات لازم مانند نام فیلدها، جداول و یا تعاریف روابط ویژه نیز استفاده می‌گردد. به علاوه در روش Code first یک API جدید به نام Fluent API نیز جهت تعاریف این ویژگی‌ها و روابط، با کدنویسی مستقیم نیز درنظر گرفته شده است. نهایتا از این اطلاعات جهت نگاشت کلاس‌ها به بانک اطلاعاتی و یا برای تولید ساختار یک بانک اطلاعاتی خالی جدید نیز می‌توان کمک گرفت.



مزایای EF Code first

- مطلوب برنامه نویس‌ها! : برنامه نویس‌هایی که مدتی تجربه کار با ابزارهای طراح را داشته باشند به خوبی می‌دانند این نوع ابزارها عموما demo-ware هستند. چندجا کلیک می‌کنید، دوبار Next، سه بار OK و ... به نظر می‌رسد کار تمام شده. اما واقعیت این است که عمری را باید صرف نگهداری و یا پیاده سازی جزئیاتی کرد که انجام آن‌ها با کدنویسی مستقیم بسیار سریعتر، ساده‌تر و با کنترل بیشتری قابل انجام است.
- سرعت: برای کار با EF Code first نیازی نیست در ابتدای کار بانک اطلاعاتی خاصی وجود داشته باشد. کلا‌س‌های خود را طراحی و شروع به کدنویسی کنید.
- سادگی: در اینجا دیگر از فایل‌های EDMX خبری نیست و نیازی نیست مرتبا آن‌ها را به روز کرده یا نگهداری کرد. تمام کارها را با کدنویسی و کنترل بیشتری می‌توان انجام داد. به علاوه کنترل کاملی بر روی کد نهایی تهیه شده نیز وجود دارد و توسط ابزارهای تولید کد، ایجاد نمی‌شوند.
- طراحی بهتر بانک اطلاعاتی نهایی: اگر طرح دقیقی از مدل‌های برنامه داشته باشیم، می‌توان آن‌ها را به المان‌های کوچک و مشخصی، تقسیم و refactor کرد. همین مساله در نهایت مباحث database normalization را به نحوی مطلوب و با سرعت بیشتری میسر می‌کند.
- امکان استفاده مجدد از طراحی کلاس‌های انجام شده در سایر ORMهای دیگر. چون طراحی مدل‌های برنامه به بانک اطلاعاتی خاصی گره نمی‌خورند و همچنین الزاما هم قرار نیست جزئیات کاری EF در آن‌ها لحاظ شود، این کلاس‌ها در صورت نیاز در سایر پروژه‌ها نیز به سادگی قابل استفاده هستند.
- ردیابی ساده‌تر تغییرات: روش اصولی کار با پروژه‌های نرم افزاری همواره شامل استفاده از یک ابزار سورس کنترل مانند SVN، Git، مرکوریال و امثال آن است. به این ترتیب ردیابی تغییرات انجام شده به سادگی توسط این ابزارها میسر می‌شوند.
- ساده‌تر شدن طراحی‌های پیچیده‌تر: برای مثال پیاده سازی ارث بری،‌ ایجاد کلاس‌های خود ارجاع دهنده و امثال آن با کدنویسی ساده‌تر است.


دریافت آخرین نگارش EF


برای دریافت و نصب آخرین نگارش EF نیاز است از NuGet استفاده شود و این مزایا را به همراه دارد:
به کمک NuGet امکان با خبر شدن از به روز رسانی جدید صورت گرفته به صورت خودکار درنظر گرفته شده است و همچنین کار دریافت بسته‌های مرتبط و به روز رسانی ارجاعات نیز در این حالت خودکار است. به علاوه توسط NuGet امکان دسترسی به کتابخانه‌هایی که مثلا در گوگل‌کد قرار دارند و به صورت معمول امکان دریافت آن‌ها برای ما میسر نیست، نیز بدون مشکل فراهم است (برای نمونه ELMAH، که اصل آن از گوگل‌کد قابل دریافت است؛ اما بسته نیوگت آن نیز در دسترس می‌باشد).
پس از نصب NuGet، تنها کافی است بر روی گره References در Solution explorer ویژوال استودیو، کلیک راست کرده و به کمک NuGet آخرین نگارش EF را نصب کرد. در گالری آنلاین آن، عموما EF اولین گزینه است (به علت تعداد بالای دریافت آن).
حین استفاده از NuGet جهت نصب Ef، ابتدا ارجاعاتی به اسمبلی‌های زیر به برنامه اضافه خواهند شد:
System.ComponentModel.DataAnnotations.dll
System.Data.Entity.dll
EntityFramework.dll
بدیهی است بدون استفاده از NuGet، تمام این کارها را باید دستی انجام داد.
سپس در پوشه‌ای به نام packages، فایل‌های مرتبط با EF قرار خواهند گرفت که شامل اسمبلی آن به همراه ابزارهای DB Migration است. همچنین فایل packages.config که شامل تعاریف اسمبلی‌های نصب شده است به پروژه اضافه می‌شود. NuGet به کمک این فایل و شماره نگارش درج شده در آن، شما را از به روز رسانی‌های بعدی مطلع خواهد ساخت:

<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="EntityFramework" version="4.3.1" />
</packages>

همچنین اگر به فایل app.config یا web.config برنامه نیز مراجعه کنید، یک سری تنظیمات ابتدایی اتصال به بانک اطلاعاتی در آن ذکر شده است:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.3.1.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</configSections>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework">
<parameters>
<parameter value="Data Source=(localdb)\v11.0; Integrated Security=True; MultipleActiveResultSets=True" />
</parameters>
</defaultConnectionFactory>
</entityFramework>
</configuration>

همانطور که ملاحظه می‌کنید بانک اطلاعاتی پیش فرضی که در اینجا ذکر شده است، LocalDB می‌باشد. این بانک اطلاعاتی را از این آدرس‌ نیز می‌توانید دریافت کنید.

البته ضرورتی هم به استفاده از آن نیست و از سایر نگارش‌های SQL Server نیز می‌توان استفاده کرد ولی خوب ... مزیت استفاده از آن برای کاربر نهایی این است که «نیازی به یک مهندس برای نصب، راه اندازی و نگهداری ندارد». تنها مشکل آن این است که از ویندوز XP پشتیبانی نمی‌کند. البته SQL Server CE 4.0 این محدودیت را ندارد.
ضمن اینکه باید درنظر داشت EF به فناوری میزبان خاصی گره نخورده است و مثال‌هایی که در اینجا بررسی می‌شوند صرفا تعدادی برنامه کنسول معمولی هستند و نکات عنوان شده در آن‌ها در تمام فناوری‌های میزبان موجود به یک نحو کاربرد دارند.


قراردادهای پیش فرض EF Code first

عنوان شد که اطلاعات کلاس‌های ساده تشکیل دهنده مدل‌های برنامه، برای تعریف جداول و فیلدهای یک بانک اطلاعات و همچنین مشخص سازی روابط بین آن‌ها کافی نیستند و مرسوم است برای پر کردن این خلاء از یک سری متادیتا و یا Fluent API مهیا نیز استفاده گردد. اما در EF Code first یک سری قرار داد توکار نیز وجود دارند که مطلع بودن از آن‌ها سبب خواهد شد تا حجم کدنویسی و تنظیمات جانبی این فریم ورک به حداقل برسند. برای نمونه مدل‌های معروف بلاگ و مطالب آن‌را درنظر بگیرید:

namespace EF_Sample01.Models
{
public class Post
{
public int Id { set; get; }
public string Title { set; get; }
public string Content { set; get; }
public virtual Blog Blog { set; get; }
}
}

using System.Collections.Generic;

namespace EF_Sample01.Models
{
public class Blog
{
public int Id { set; get; }
public string Title { set; get; }
public string AuthorName { set; get; }
public IList<Post> Posts { set; get; }
}
}


یکی از قراردادهای EF Code first این است که کلاس‌های مدل شما را جهت یافتن خاصیتی به نام Id یا ClassId مانند BlogId، جستجو می‌کند و از آن به عنوان primary key و فیلد identity جدول بانک اطلاعاتی استفاده خواهد کرد.
همچنین در کلاس Blog، خاصیت لیستی از Posts و در کلاس Post خاصیت virtual ایی به نام Blog وجود دارند. به این ترتیب روابط بین دو کلاس و ایجاد کلید خارجی متناظر با آن‌را به صورت خودکار انجام خواهد داد.
نهایتا از این اطلاعات جهت تشکیل database schema یا ساختار بانک اطلاعاتی استفاده می‌گردد.
اگر به فضاهای نام دو کلاس فوق دقت کرده باشید، به کلمه Models ختم شده‌اند. به این معنا که در پوشه‌ای به همین نام در پروژه جاری قرار دارند. یا مرسوم است کلاس‌های مدل را در یک پروژه class library مجزا به نام DomainClasses نیز قرار دهند. این پروژه نیازی به ارجاعات اسمبلی‌های EF ندارد و تنها به اسمبلی System.ComponentModel.DataAnnotations.dll نیاز خواهد داشت.


EF Code first چگونه کلاس‌های مورد نظر را انتخاب می‌کند؟

ممکن است ده‌ها و صدها کلاس در یک پروژه وجود داشته باشند. EF Code first چگونه از بین این کلاس‌ها تشخیص خواهد داد که باید از کدامیک استفاده کند؟ اینجا است که مفهوم جدیدی به نام DbContext معرفی شده است. برای تعریف آن یک کلاس دیگر را به پروژه برای مثال به نام Context اضافه کنید. همچنین مرسوم است که این کلاس را در پروژه class library دیگری به نام DataLayer اضافه می‌کنند. این پروژه نیاز به ارجاعی به اسمبلی‌های EF خواهد داشت. در ادامه کلاس جدید اضافه شده باید از کلاس DbContext مشتق شود:

using System.Data.Entity;
using EF_Sample01.Models;

namespace EF_Sample01
{
public class Context : DbContext
{
public DbSet<Blog> Blogs { set; get; }
public DbSet<Post> Posts { set; get; }
}
}

سپس در اینجا به کمک نوع جنریکی به نام DbSet، کلاس‌های دومین برنامه را معرفی می‌کنیم. به این ترتیب، EF Code first ابتدا به دنبال کلاسی مشتق شده از DbContext خواهد گشت. پس از یافتن آن‌، خواصی از نوع DbSet را بررسی کرده و نوع‌های متناظر با آن‌را به عنوان کلاس‌های دومین درنظر می‌گیرد و از سایر کلاس‌های برنامه صرفنظر خواهد کرد. این کل کاری است که باید انجام شود.
اگر دقت کرده باشید، نام کلاس‌های موجودیت‌ها، مفرد هستند و نام خواص تعریف شده به کمک DbSet‌، جمع می‌باشند که نهایتا متناظر خواهند بود با نام جداول بانک اطلاعاتی تشکیل شده.


تشکیل خودکار بانک اطلاعاتی و افزودن اطلاعات به جداول

تا اینجا بدون تهیه یک بانک اطلاعاتی نیز می‌توان از کلاس Context تهیه شده استفاده کرد و کار کدنویسی را آغاز نمود. بدیهی است جهت اجرای نهایی کدها، نیاز به یک بانک اطلاعاتی خواهد بود. اگر تنظیمات پیش فرض فایل کانفیگ برنامه را تغییر ندهیم، از همان defaultConnectionFactory یاده شده استفاده خواهد کرد. در این حالت نام بانک اطلاعاتی به صورت خودکار تنظیم شده و مساوی «EF_Sample01.Context» خواهد بود.
برای سفارشی سازی آن نیاز است فایل app.config یا web.config برنامه را اندکی ویرایش نمود:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
...
</configSections>
<connectionStrings>
<clear/>
<add name="Context"
connectionString="Data Source=(local);Initial Catalog=testdb2012;Integrated Security = true"
providerName="System.Data.SqlClient"
/>
</connectionStrings>
...
</configuration>

در اینجا به بانک اطلاعاتی testdb2012 در وهله پیش فرض SQL Server نصب شده، اشاره شده است. فقط باید دقت داشت که تگ configSections باید در ابتدای فایل قرار گیرد و مابقی تنظیمات پس از آن.
یا اگر علاقمند باشید که از SQL Server CE استفاده کنید، تنظیمات رشته اتصالی را به نحو زیر مقدار دهی نمائید:

<connectionStrings> 
              <add name="MyContextName"
                         connectionString="Data Source=|DataDirectory|\Store.sdf"
                         providerName="System.Data.SqlServerCe.4.0" />
</connectionStrings>

در هر دو حالت، name باید به نام کلاس مشتق شده از DbContext اشاره کند که در مثال جاری همان Context است.
یا اگر علاقمند بودید که این قرارداد توکار را تغییر داده و نام رشته اتصالی را با کدنویسی تعیین کنید، می‌توان به نحو زیر عمل کرد:

public class Context : DbContext
{
    public Context()
      : base("ConnectionStringName")
    {
    }


البته ضرورتی ندارد این بانک اطلاعاتی از پیش موجود باشد. در اولین بار اجرای کدهای زیر، به صورت خودکار بانک اطلاعاتی و جداول Blogs و Posts و روابط بین آن‌ها تشکیل می‌گردد:

using EF_Sample01.Models;

namespace EF_Sample01
{
class Program
{
static void Main(string[] args)
{
using (var db = new Context())
{
db.Blogs.Add(new Blog { AuthorName = "Vahid", Title = ".NET Tips" });
db.SaveChanges();
}
}
}
}


در این تصویر چند نکته حائز اهمیت هستند:
الف) نام پیش فرض بانک اطلاعاتی که به آن اشاره شد (اگر تنظیمات رشته اتصالی قید نگردد).
ب) تشکیل خودکار primary key از روی خواصی به نام Id
ج) تشکیل خودکار روابط بین جداول و ایجاد کلید خارجی (به کمک خاصیت virtual تعریف شده)
د) تشکیل جدول سیستمی به نام dbo.__MigrationHistory که از آن برای نگهداری سابقه به روز رسانی‌های ساختار جداول کمک گرفته خواهد شد.
ه) نوع و طول فیلدهای متنی، nvarchar از نوع max است.

تمام این‌ها بر اساس پیش فرض‌ها و قراردادهای توکار EF Code first انجام شده است.

در کدهای تعریف شده نیز، ابتدا یک وهله از شیء Context ایجاد شده و سپس به کمک آن می‌توان به جدول Blogs اطلاعاتی را افزود و در آخر ذخیره نمود. استفاده از using هم دراینجا نباید فراموش شود، زیرا اگر استثنایی در این بین رخ دهد، کار پاکسازی منابع و بستن اتصال گشوده شده به بانک اطلاعاتی به صورت خودکار انجام خواهد شد.
در ادامه اگر بخواهیم مطلبی را به Blog ثبت شده اضافه کنیم، خواهیم داشت:

using EF_Sample01.Models;

namespace EF_Sample01
{
class Program
{
static void Main(string[] args)
{
//addBlog();
addPost();
}

private static void addPost()
{
using (var db = new Context())
{
var blog = db.Blogs.Find(1);
db.Posts.Add(new Post
{
Blog = blog,
Content = "data",
Title = "EF"
});
db.SaveChanges();
}
}

private static void addBlog()
{
using (var db = new Context())
{
db.Blogs.Add(new Blog { AuthorName = "Vahid", Title = ".NET Tips" });
db.SaveChanges();
}
}
}
}

متد db.Blogs.Find، بر اساس primary key بلاگ ثبت شده، یک وهله از آن‌را یافته و سپس از آن جهت تشکیل شیء Post و افزودن آن به جدول Posts استفاده می‌شود. متد Find ابتدا Contxet جاری را جهت یافتن شیءایی با id مساوی یک جستجو می‌کند (اصطلاحا به آن first level cache هم گفته می‌شود). اگر موفق به یافتن آن شد، بدون صدور کوئری اضافه‌ای به بانک اطلاعاتی از اطلاعات همان شیء استفاده خواهد کرد. در غیراینصورت نیاز خواهد داشت تا ابتدا کوئری لازم را به بانک اطلاعاتی ارسال کرده و اطلاعات شیء Blog متناظر با id=1 را دریافت کند. همچنین اگر نیاز داشتیم تا تنها با سطح اول کش کار کنیم، در EF Code first می‌توان از خاصیتی به نام Local نیز استفاده کرد. برای مثال خاصیت db.Blogs.Local بیانگر اطلاعات موجود در سطح اول کش می‌باشد.
نهایتا کوئری Insert تولید شده توسط آن به شکل زیر خواهد بود (لاگ شده توسط برنامه SQL Server Profiler):

exec sp_executesql N'insert [dbo].[Posts]([Title], [Content], [Blog_Id])
values (@0, @1, @2)
select [Id]
from [dbo].[Posts]
where @@ROWCOUNT > 0 and [Id] = scope_identity()',
N'@0 nvarchar(max) ,@1 nvarchar(max) ,@2 int',
@0=N'EF',
@1=N'data',
@2=1


این نوع کوئرهای پارامتری چندین مزیت مهم را به همراه دارند:
الف) به صورت خودکار تشکیل می‌شوند. تمام کوئری‌های پشت صحنه EF پارامتری هستند و نیازی نیست مرتبا مزایای این امر را گوشزد کرد و باز هم عده‌ای با جمع زدن رشته‌ها نسبت به نوشتن کوئری‌های نا امن SQL اقدام کنند.
ب) کوئرهای پارامتری در مقابل حملات تزریق اس کیوال مقاوم هستند.
ج) SQL Server با کوئری‌های پارامتری همانند رویه‌های ذخیره شده رفتار می‌کند. یعنی query execution plan محاسبه شده آن‌ها را کش خواهد کرد. همین امر سبب بالا رفتن کارآیی برنامه در فراخوانی‌های بعدی می‌گردد. الگوی کلی مشخص است. فقط پارامترهای آن تغییر می‌کنند.
د) مصرف حافظه SQL Server کاهش می‌یابد. چون SQL Server مجبور نیست به ازای هر کوئری اصطلاحا Ad Hoc رسیده یکبار execution plan متفاوت آن‌ها را محاسبه و سپس کش کند. این مورد مشکل مهم تمام برنامه‌هایی است که از کوئری‌های پارامتری استفاده نمی‌کنند؛ تا حدی که گاهی تصور می‌کنند شاید SQL Server دچار نشتی حافظه شده، اما مشکل جای دیگری است.


مشکل! ساختار بانک اطلاعاتی تشکیل شده مطلوب کار ما نیست.

تا همینجا با حداقل کدنویسی و تنظیمات مرتبط با آن، پیشرفت خوبی داشته‌ایم؛ اما نتیجه حاصل آنچنان مطلوب نیست و نیاز به سفارشی سازی دارد. برای مثال طول فیلدها را نیاز داریم به مقدار دیگری تنظیم کنیم، تعدادی از فیلدها باید به صورت not null تعریف شوند یا نام پیش فرض بانک اطلاعاتی باید مشخص گردد و مواردی از این دست. با این موارد در قسمت‌های بعدی بیشتر آشنا خواهیم شد.
اشتراک‌ها
HarfBuzz 10‌ منتشر شد
کتابخانه‌ی گرافیکی چندسکویی SkiaSharp، از «حرف‌باز» برای نمایش صحیح متون راست به چپ، کمک می‌گیرد. SkiaSharp در پشت صحنه از کتابخانه‌ی Skia استفاده می‌کند که موتور گرافیکی مرورگر کروم است.
HarfBuzz 10‌ منتشر شد
نظرات مطالب
غیرمعتبر کردن توکن و یا کوکی سرقت شده در برنامه‌های مبتنی بر ASP.NET Core

یک نکته‌ی تکمیلی: گوگل برای مواجه شدن با یک چنین مشکلاتی،‌ در حال پیاده سازی «device bound sessions» است. همچنین نحوه‌ی رمزنگاری اطلاعات کوکی‌های کروم نیز در ویندوز به‌روز خواهد شد و دیگر صرفا از API خود ویندوز استفاده نمی‌کنند.

نظرات مطالب
نحوه ارتقاء برنامه‌های موجود MVC3 به MVC4
نیاز هست با روش دیباگ این نوع برنامه‌ها بیشتر آشنا شوید. اطلاعات بیشتر
توسط فایرباگ یا حتی کنسول کروم بررسی کنید چه خطاهایی گرفتید، چه فایل‌هایی را گزارش می‌دهد که یافت نشد و امثال آن. بر این اساس باید برنامه را دیباگ و رفع اشکال کرد.
نظرات مطالب
ارسال مستقیم یک فایل PDF به چاپگر
چه خوب ، نکته جالب اینه pdf  خوان داخلی کروم هم از این قابلیت پشتیبانی میکنه و برای یک برنامه وب می‌تونه تداعی کننده print perview یک برنامه ویندوزی باشه.
اشتراک‌ها
معرفی Script#؛ اسکریپت نویسی با جاوا‌اسکریپت در دات‌نت

#Script is a simple, fast, highly versatile and embeddable scripting language for .NET Core and .NET Apps that utilizes a familiar JavaScript inspired expressive Syntax to enable dynamic scripting of .NET Apps via controlled access to pluggable methods and arguments within a sandbox environment - ensuring scripts are encapsulated and encourages the use of reusable and testable components where live environments can be easily re-created and simulated.  

معرفی Script#؛ اسکریپت نویسی با جاوا‌اسکریپت در دات‌نت
مطالب
بازسازی کد: جایگزینی نوع‌های داده‌های یک کلاس با زیر کلاس‌ها
یک پیاده سازی از کلاس، می‌تواند به طور ضمنی شامل دو یا چند نوع (Type) باشد. یکی از ساده‌ترین راه‌های پیاده سازی این حالت، استفاده از فیلدهایی برای نگهداری نوع اصلی داده‌ی کلاس است که اصطلاحا Type code نیز نامیده می‌شوند. به طور مثال پیاده سازی زیر را در نظر بگیرید. 

به طور مثال در کلاس بالا یک کارمند می‌تواند فروشنده یا مهندس باشد. پیاده سازی بالا این مورد را با استفاده از دو فیلد نشان داده‌است که در صورت true بودن، مقدار هریک از آن‌ها، نوع کلاس متناظر با آن خواهد بود.

مثلا اگر IsSalesman مقدار true داشته باشد، شیء ما کارمندی با نقش Salesman است و در صورتی که IsEngineer مقدار true داشته باشد ، شیء کارمند، نقش مهندس دارد. بماند که حالت‌های دیگری نیز برای مقادیر این فیلدها وجود دارند! 

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

اگر با همین فرمان کدنویسی را ادامه دهیم احتمالا با کلاسی روبرو خواهیم شد که پر است از گذاره‌های if else ، switch و یا مواردی از این دست؛ که ابدا شرایط دلپذیری برای دوستانی که قصد نگهداری از کد ما را دارند، نیست! 

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

مراحل انجام این بازسازی کد  

  1. اگر type کد درونی کلاس از طریق سازنده به کلاس ارسال شده است، این سازنده را با یک متد سازنده (Factory method) جایگزین کنید. 
  2. به ازای هر مقدار از type کدهای درونی کلاس، یک زیر کلاس جدید بسازید. 
  3. تمامی استفاده‌ها از type کدهای درونی کلاس را بازسازی کرده و به کلاس‌های مربوط به خود منتقل کنید (احتمالا تمامی پیاده سازی‌هایی که if else یا switch ای بر روی مقدار type کدها دارند).
  4. از کلاس پایه، type کد را حذف کنید. 
  5. در صورت وجود تمامی استفاده‌ها از سازنده، کلاس اولیه را به استفاده از متد سازنده تغییر دهید. 
  6. کد را کامپایل و تست نمایید.
نظرات اشتراک‌ها
HTML Helper برای jqGrid
اگر این کتابخانه‌ها نبودند و امروزه تا این حد تکامل پیدا نکرده بودند، هیچ وقت سیلورلایت و فلش از صحنه روزگار محو نمی‌شدند. در بسیاری از اوقات هدف ساخت یک برنامه غنی وب است. برنامه‌ای که تجربه کاربری آن همانند برنامه‌های دسکتاپ باشد. مثلا صفحه مدام چشمک نمی‌زند و کاربر احساس نمی‌کند که مدام رفت و برگشت به سرور وجود دارد، کنترل‌های auto-complete مانند برنامه‌های دسکتاپ و یا حتی شکیل‌تر و غنی‌تر از آن‌ها در وب وجود دارند، برنامه‌های تک صفحه‌ای وب، اعتبار سنجی‌های سمت کاربر، بدون هدایت او به سرور و دریافت پاسخ آنی و بسیاری از مثال‌های دیگری که در جهت بهبود کاربری در وب مطرح هستند. در اینجا HTML خالص بدون جاوا اسکریپت حرفی برای گفتن ندارد. HTML خالص صرفا جهت ارائه محتوا اختراع شده است نه طراحی برنامه‌های غنی وب و کار ما هم با ASP.NET و یا فناوری‌های مشابه، تولید برنامه‌های وب است و نه صرفا ارائه محتوا. اگر قرار است مثلا چند صفحه توضیح مشخصات شرکتی را در اینترنت قرار دهید، این تنها به معنای ارائه‌ی محتوا است. نیازی به برنامه خاصی ندارد. چند صفحه HTML به همراه مقداری هم CSS برای اینکار کافی است. اما اگر همینجا قرار شد از کاربر اطلاعات دریافت کنید، نیاز است تجربه کاربری او را غنی کنید.