سورس باز شدن WCF
We’re excited to announce a new open source project on GitHub from the WCF team at Microsoft. This new version of WCF targets .NET Core and has been donated to the family of .NET Foundation open source projects.
ایجاد پروژهی ASP.NET Core Web API
برای تامین اطلاعات برنامهی سمت کلاینت Blazor WASM و همچنین فراهم آوردن زیرساخت اعتبارسنجی کاربران آن، نیاز به یک پروژهی ASP.NET Core Web API داریم که آنرا با اجرای دستور dotnet new webapi در یک پوشهی خالی، برای مثال به نام BlazorWasm.WebApi ایجاد میکنیم.
البته این پروژه، از زیرساختی که در برنامهی Blazor Server بررسی شدهی تا این قسمت، ایجاد کردیم نیز استفاده خواهد کرد. همانطور که پیشتر نیز عنوان شد، هدف از قسمت Blazor Server مثال این سری، آشنایی با مدل برنامه نویسی خاص آن بود؛ وگرنه میتوان کل این پروژه را با Blazor Server و یا کل آنرا با Web API + Blazor WASM نیز پیاده سازی کرد. در این مثال، قسمتهای مدیریتی برنامهی مدیریت هتل را توسط Blazor Server (مانند قسمتهای تعریف اتاقها و امکانات رفاهی هتل) و قسمت مخصوص کاربران آنرا مانند رزرو کردن اتاقها، توسط Blazor WASM پیاده سازی میکنیم. به همین جهت قسمتهایی از این دو پروژه، مانند سرویسهای استفاده شدهی در پروژهی Blazor server، در پروژهی Web API مکمل Blazor WASM، قابلیت استفادهی مجدد را دارند.
افزودن سرویسهای آغازین مورد نیاز، به پروژهی Web API
در فایل آغازین BlazorWasm\BlazorWasm.WebApi\Startup.cs، برای شروع به تکمیل Web API، نیاز به این سرویسها را داریم:
namespace BlazorWasm.WebApi { public class Startup { //... public void ConfigureServices(IServiceCollection services) { services.AddAutoMapper(typeof(MappingProfile).Assembly); services.AddScoped<IHotelRoomService, HotelRoomService>(); services.AddScoped<IAmenityService, AmenityService>(); services.AddScoped<IHotelRoomImageService, HotelRoomImageService>(); var connectionString = Configuration.GetConnectionString("DefaultConnection"); services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(connectionString)); services.AddIdentity<IdentityUser, IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultTokenProviders(); //...
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>net5.0</TargetFramework> </PropertyGroup> <ItemGroup> <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="8.1.1" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\..\BlazorServer\BlazorServer.DataAccess\BlazorServer.DataAccess.csproj" /> <ProjectReference Include="..\..\BlazorServer\BlazorServer.Services\BlazorServer.Services.csproj" /> <ProjectReference Include="..\..\BlazorServer\BlazorServer.Models.Mappings\BlazorServer.Models.Mappings.csproj" /> </ItemGroup> </Project>
{ "ConnectionStrings": { "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=HotelManagement;Trusted_Connection=True;MultipleActiveResultSets=true" } }
تعریف کنترلر HotelRoom
در ادامه کدهای اولین کنترلر Web API را مشاهده میکنید که مرتبط است با بازگشت اطلاعات تمام اتاقهای ثبت شده و یا بازگشت اطلاعات یک اتاق ثبت شده:
using BlazorServer.Models; using BlazorServer.Services; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using System.Threading.Tasks; namespace BlazorWasm.WebApi.Controllers { [Route("api/[controller]")] public class HotelRoomController : ControllerBase { private readonly IHotelRoomService _hotelRoomService; public HotelRoomController(IHotelRoomService hotelRoomService) { _hotelRoomService = hotelRoomService; } [HttpGet] public IAsyncEnumerable<HotelRoomDTO> GetHotelRooms() { return _hotelRoomService.GetAllHotelRoomsAsync(); } [HttpGet("{roomId}")] public async Task<IActionResult> GetHotelRoom(int? roomId) { if (roomId == null) { return BadRequest(new ErrorModel { Title = "", ErrorMessage = "Invalid Room Id", StatusCode = StatusCodes.Status400BadRequest }); } var roomDetails = await _hotelRoomService.GetHotelRoomAsync(roomId.Value); if (roomDetails == null) { return BadRequest(new ErrorModel { Title = "", ErrorMessage = "Invalid Room Id", StatusCode = StatusCodes.Status404NotFound }); } return Ok(roomDetails); } } }
- ErrorModel آنرا در همان پروژهی قبلی مدلها، در فایل BlazorServer\BlazorServer.Models\ErrorModel.cs به صورت زیر ایجاد کردهایم:
namespace BlazorServer.Models { public class ErrorModel { public string Title { get; set; } public int StatusCode { get; set; } public string ErrorMessage { get; set; } } }
یکی از مزایای آن، امکان آزمایش API تهیه شده، بدون نیاز به تهیهی هیچ نوع کلاینت خاصی است. برای مثال اگر بر روی api/hotelroom آن کلیک کنیم، گزینهی «try it out» آن ظاهر شده و با کلیک بر روی آن، اینبار دکمهی execute ظاهر میشود. در ادامه با کلیک بر روی دکمهی اجرای آن، اکشن متد GetHotelRooms اجرا شده و خروجی زیر ظاهر میشود:
و یا اگر بخواهیم متد GetHotelRoom را توسط آن آزمایش کنیم، بر اساس پارامترهای آن، رابط کاربری زیر را تشکیل میدهد که امکان دریافت شمارهی اتاق را دارد:
انجام تنظیمات ابتدایی CORS و خروجی JSON برنامه
قرار است این API را از طریق پروژهی Blazor سمت کلاینت خود استفاده کنیم که آدرس آن، با آدرس API یکی نیست. به همین جهت نیاز است تنظیمات CORS را به صورت زیر اضافه کنیم:
namespace BlazorWasm.WebApi { public class Startup { public void ConfigureServices(IServiceCollection services) { // ... services.AddCors(o => o.AddPolicy("HotelManagement", builder => { builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader(); })); services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.PropertyNamingPolicy = null; // To avoid `JsonSerializationException: Self referencing loop detected error` options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve; }); // ... } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // ... app.UseCors("HotelManagement"); app.UseRouting(); app.UseAuthentication(); // ... } } }
کدهای کامل این مطلب را از اینجا میتوانید دریافت کنید: Blazor-5x-Part-24.zip
اولین پروژه
معمولا برای شروع از تاریخچه و توضیحات دیگر استفاده میکنند اما روش آموزشی که در پیش خواهیم گرفت با انجام پروژههای عملی بوده و هر جا که نیاز به توضیح باشد ، بیان میکنیم ...
ایجاد اولین پروژه Win32 Console Application
ویژوال استادیو را اجرا نمایید و از گزینه File -> New -> Project و سپس طبق عکس زیر پروژه Win32 Console Application را انتخاب نمایید ، دقت کنید که زبان انتخاب شده ++Visual C باشد.
در این مرحله میتوانید محل ذخیره شده پروژه را در قسمت Location تنظیم نمایید و از قسمت Name میتوانید نام دلخواه را وارد کنید در حالت پیش فرض اگر اولین پروژه Win32 Console در مسیر تعین شدهی قسمت Location باشد ، نام ConsoleApplication1 قرار گرفته است . پس از تنظیمات Ok کنید .
در این مرحله Next را بزنید .
در این مرحله در قسمت Additional options تیک Empty project را بزنید ، همانند عکس فوق تنظیمات را انجام دهید .
پس از انجام مراحل فوق پروژه بصورت شکل زیر ظاهر میشود .
برای کد نویسی روی نام پروژه که در اینجا ConsoleApplication1 میباشد ، راست کلیک میکنیم و گزینه Add و سپس New Item را انتخاب میکنیم .
طبق عکس زیر فایل با پسوند cpp را انتخاب و Add میکنیم .
فایلی که اکنون به پروژه اضافه کردیم خالی و با نام پیش فرض Source.cpp میباشد ، دستورات زیر را در آن تایپ کنید .حال پروژه به شکل زیر خواهد بود .
#include<iostream> int main() { std::cout<<"Hello world ...\n"; return 0; }
برای اجرای پروژه کلید F5 را فشار دهید و اگر میخواهید نتیجه کار را مشاهده کنید کلید Ctrl + F5 را امتحان کنید .
شما اولین پروژه VC++ را اجرا نمودید ( آفرین ) .
اما توضیحات :
خط اول برنامه یک راهنمای پیش پردازنده است ، کاراکتر # که نشان میدهد این خط یک راهنمای پیش پردازنده است و بعد عبارت include و نام یک فایل کتابخانه ای که بین علامت <> قرار داده شده ، فایل سرآیند استفاده شده در اینجا iostream میباشد . (به فایلهای کتابخانه ای ، فایلهای سرآیند (Header Files) نیز گفته میشود. ) راهنمای پیش پردازنده خطی است که به کامپایلر اطلاع میدهد در برنامه موجودیتی است که تعریف آن را در فایل سرآیند مذکور جستجو کند . در این برنامه از std::cout استفاده شده ، که کامپایلر در مورد آن چیزی نمیداند لذا به فایل iostream مراجعه نموده ، تعریف آن را مییابد و آن را اجرا میکند .
خط 3 :
بخشی از هر برنامه تابع میباشد . پرانتزهای واقع پس از آن main نشان میدهند که main یک بلوک برنامه بنام تابع است. برنامهها میتوانند حاوی یک یا چندین تابع باشند، اما main تابع اصلی برنامه است که وجود آن الزامی میباشد . کلمه کلیدی int که در سمت چپ main قرار گرفته، بر این نکته دلالت دارد که main یک مقدار صحیح برمیگرداند.
خط 5 :
با استفاده از این دستور رشته ای را به خروجی استاندارد که معمولا صفحه نمایش باشد ارسال میکنیم .
خط 6 :
که ;0 return میباشد مقدار برگشتی تابع را مشخص میکند در حقیقت این خط که مقدار 0 را برمیگرادند نشان دهنده اتمام موفقیت آمیز برنامه میباشد .
به مرور زمان نسبت به موارد بالا بیشتر و مفصل صحبت خواهیم نمود .
LocalDB FAQ
در تنظیمات Data Source جهت اتصال به LocalDB در Rider این مراحل باید طی شوند:
- پیش از هر کاری دو دستور زیر را اجرا کنید:
C:\>"C:\Program Files\Microsoft SQL Server\140\Tools\Binn\SqlLocalDB.exe" i MSSQLLocalDB ProjectsV13 v12.0 C:\>"C:\Program Files\Microsoft SQL Server\140\Tools\Binn\SqlLocalDB.exe" s MSSQLLocalDB LocalDB instance "MSSQLLocalDB" started.
خود Rider آغازگر این وهلهها نخواهد بود. به همین جهت نیاز است دستی آغاز شوند.
- سپس در صفحه تنظیمات Data Source، نوع Driver را بر روی SQL Server (jTds) قرار دهید.
- پایین صفحه، لینک download missing driver files ظاهر میشود. بر روی آن کلیک کنید تا به سرعت کار نصب و راه اندازی درایور کم حجم آن انجام شود.
- اکنون میتوانید در قسمت URL، گزینهی LocalDB و سپس وهلهی MSSQLLocalDB را از لیست Instance انتخاب کنید.
- در آخر بر روی دکمهی Test Connection کلیک کنید. اگر درایور را نصب نکرده باشید، این دکمه قابل انتخاب نخواهد بود.
تغییر نوع DbContext برنامه
پیش از شروع به یکپارچه کردن ASP.NET Core Identity با برنامهی جاری، نیاز است نوع DbContext آنرا به صورت زیر تغییر داد:
using BlazorServer.Entities; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; namespace BlazorServer.DataAccess { public class ApplicationDbContext : IdentityDbContext { // ...
- این تغییر، نیاز به نصب بستهی نیوگت Microsoft.AspNetCore.Identity.EntityFrameworkCore را نیز در پروژهی جاری دارد تا IdentityDbContext آن شناسایی شده و قابل استفاده شود.
نصب ابزار تولید کدهای ASP.NET Core Identity
اگر از ویژوال استودیوی کامل استفاده میکنید، گزینهی افزودن کدهای ASP.NET Core Identity به صورت زیر قابل دسترسی است:
project -> right-click > Add > New Scaffolded Item -> select Identity > Add
dotnet tool install -g dotnet-aspnet-codegenerator
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design dotnet add package Microsoft.EntityFrameworkCore.Design dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore dotnet add package Microsoft.AspNetCore.Identity.UI dotnet add package Microsoft.EntityFrameworkCore.SqlServer dotnet add package Microsoft.EntityFrameworkCore.Tools
dotnet aspnet-codegenerator identity --dbContext BlazorServer.DataAccess.ApplicationDbContext --force
حال اگر به پروژه دقت کنیم، پوشهی جدید Areas که به همراه فایلهای مدیریتی ASP.NET Core Identity است، اضافه شده و حاوی کدهای صفحات لاگین، ثبت نام کاربر و غیره است.
اعمال تغییرات ابتدایی مورد نیاز جهت استفاده از ASP.NET Core Identity
تا اینجا کدهای پیشفرض مدیریتی ASP.NET Core Identity را به پروژه اضافه کردیم. در ادامه نیاز است تغییرات ذیل را به پروژهی اصلی Blazor Server اعمال کنیم تا بتوان از این فایلها استفاده کرد:
- به فایل BlazorServer.App\Startup.cs مراجعه کرده و UseAuthentication و UseAuthorization را دقیقا در محلی که مشاهده میکنید، اضافه میکنیم. همچنین در اینجا نیاز است مسیریابیهای razor pages را نیز فعال کرد.
namespace BlazorServer.App { public class Startup { // ... public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // ... app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); // ... }); } } }
dotnet tool update --global dotnet-ef --version 5.0.4 dotnet build dotnet ef migrations --startup-project ../BlazorServer.App/ add AddIdentity --context ApplicationDbContext dotnet ef --startup-project ../BlazorServer.App/ database update --context ApplicationDbContext
افزودن گزینهی منوی لاگین به برنامهی Blazor Server
پس از این تغییرات، به برنامهای رسیدهایم که مدیریت قسمت Identity آن، توسط قالب استاندارد مایکروسافت که در پوشهی Areas\Identity\Pages\Account نصب شده و بر اساس فناوری ASP.NET Core Razor Pages کار میکند، انجام میشود.
اکنون میخواهیم در منوی برنامهی Blazor Server خود که با صفحات Identity یکی شدهاست، لینکی را به صفحهی لاگین این Area اضافه کنیم. اگر به فایل Shared\MainLayout.razor آن مراجعه کنیم، به صورت پیشفرض، لینکی به صفحهی About، قرار دارد. به همین جهت این مورد را به صورت زیر اصلاح میکنیم:
ابتدا کامپوننت جدید BlazorServer.App\Shared\LoginDisplay.razor را با محتوای زیر ایجاد میکنیم:
<a href="Identity/Account/Register">Register</a> <a href="Identity/Account/Login">Login</a> @code { }
سپس از این کامپوننت در فایل BlazorServer.App\Shared\MainLayout.razor استفاده میکنیم:
<div class="top-row px-4"> <LoginDisplay></LoginDisplay> <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a> </div>
ثبت و فعالسازی سرویسهای کار با ASP.NET Core Identity
البته اگر در این حال برنامه را اجرا کنیم، با کلیک بر روی لینکهای فوق، استثنائی را مانند یافت نشدن سرویس UserManager، مشاهده خواهیم کرد. برای رفع این مشکل، به فایل BlazorServer.App\Startup.cs مراجعه کرده و سرویسهای Identity را ثبت میکنیم:
namespace BlazorServer.App { public class Startup { // ... public void ConfigureServices(IServiceCollection services) { // ... services.AddIdentity<IdentityUser, IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultTokenProviders() .AddDefaultUI(); // ...
همانطور که مشاهده میکنید، قالب این قسمت Identity، با قالب قسمت Blazor Server یکی نیست؛ چون توسط Razor Pages و Area آن تامین میشود که master page خاص خودش را دارد. زمانیکه قالب Identity را اضافه میکنیم، علاوه بر Area خاص خودش، پوشهی جدید Pages\Shared را نیز ایجاد میکند که قالب صفحات Identity را به کمک فایل Pages\Shared\_Layout.cshtml تامین میکند:
بنابراین سفارشی سازی قالب این قسمت، شبیه به قالبی که برای کامپوننتهای Blazor مورد استفاده قرار میگیرد، باید در اینجا انجام شود و سفارشی سازی قالب کامپوننتهای Blazor، در پوشهی Shared ای که در ریشهی پروژهاست (BlazorServer.App\Shared\MainLayout.razor) انجام میشود.
کدهای کامل این مطلب را از اینجا میتوانید دریافت کنید: Blazor-5x-Part-21.zip
SQL Server 2016 و تماس با خانه
How to Turn Off the Phone-Home Option for Standard and Enterprise Edition
Enterprise customers may construct Group Policy to opt in or out of telemetry collection by setting a registry-based policy. The relevant registry key and settings are as follows:
Key = HKEY_CURRENT_USER\Software\Microsoft\Microsoft SQL Server\130
RegEntry name = CustomerFeedback
Entry type DWORD: 0 is opt out, 1 is opt in
بعد برای استفاده از آن خواهید داشت:
using (AdomdConnection conn = new AdomdConnection("Data Source=tfsDB;Initial Catalog=Tfs_Analysis; MDX Compatibility=1;")) { conn.Open(); using (AdomdCommand cmd = new AdomdCommand(" ....... mdxQuery here ....... ", conn)) { DataSet ds = new DataSet(); ds.EnforceConstraints = false; ds.Tables.Add(); DataTable dt = ds.Tables[0]; dt.Load(cmd.ExecuteReader()); return dt; } }
IIS 7.5 که به همراه ویندوز سرور 2008 R2 ارائه میشود شامل تازههای زیر است:
- بیش از 50 مورد cmdlet جدید مخصوص Powershell جهت مدیریت IIS
- افزونههای جدید مدیریتی: Database Manager (مدیریت اس کیوال سرور از درون IIS و کنسول آن)، Configuration Editor (تولید خودکار اسکریپتهای مدیریتی جهت اتوماسیون امور مرتبط)، IIS Reports و Request Filtering .
- پشتیبانی از One-click publishing موجود در Visual Studio 10
- Web Deployment Tool یا همان MS Deploy سابق جهت مدیریت بهتر برنامههای وب.
- امکان ردیابی تغییرات در کانفیگ وب سرور
- گزارشگیری بهتر از وضعیت کارآیی سرور
- ساپورت دات نت جهت Server Core معرفی شده در ویندوز سرور 2008
- WebDav که پیشتر به صورت یک افزونهی آن معرفی شده بود، اکنون جزئی از IIS 7.5 است.
- یکپارچگی با URLScan 3.0 جهت بالا بردن امنیت وب سرور.
- FTP server services : با کنسول مدیریتی IIS یکپارچه شده است با بهبودهایی در نحوهی تنظیم کردن و ردیابی آن.
جهت مطالعه بیشتر در مورد تازههای ویندوز سرور 2008 نگارش R2 میتوان به مقالات زیر رجوع کرد:
Windows Server 2008 R2 new features - the complete list - Part 1: Virtualization
Windows Server 2008 R2 new features - the complete list - Part 2: Active Directory
Windows Server 2008 R2 new features - the complete list - Part 3: IIS 7.5 and Performance
Windows Server 2008 R2 new features - the complete list - Part 4: Administration
ایجاد مدلها و موجودیتهای برنامهی Minimal Blog
در مثال این سری، هر نویسنده میتواند بلاگ خاص خودش را داشته باشد و در هر بلاگ، تعدادی مقاله منتشر کند. هر مقاله هم میتواند تعدادی تگ یا گروه مرتبط را داشته باشد.
ساختار ابتدایی موجودیت نویسندگان مطالب بلاگ
این موجودیتها در پوشهی جدیدی به نام Model پروژهی MinimalBlog.Domain اضافه خواهند شد:
namespace MinimalBlog.Domain.Model; public class Author { public int Id { get; set; } public string FirstName { get; set; } = default!; public string LastName { get; set; } = default!; public string FullName => FirstName + " " + LastName; public DateTime DateOfBirth { get; set; } public string? Bio { get; set; } }
ساختار ابتدایی موجودیت مقالات بلاگ
namespace MinimalBlog.Domain.Model; public class Article { public Article() { Categories = new List<Category>(); } public int Id { get; set; } public string Title { get; set; } = default!; public string? Subtitle { get; set; } public string Body { get; set; } = default!; public int AuthorId { get; set; } public Author Author { get; set; } = default!; public DateTime DateCreated { get; set; } public DateTime LastUpdated { get; set; } public int NumberOfLikes { get; set; } public int NumberOfShares { get; set; } public ICollection<Category> Categories { get; set; } }
ساختار ابتدایی بلاگهای اختصاصی قابل تعریف
namespace MinimalBlog.Domain.Model; public class Blog { public Blog() { Contributors = new List<Author>(); } public int Id { get; set; } public string Name { get; set; } = default!; public string Description { get; set; } = default!; public DateTime CreatedDate { get; set; } public int AuthorId { get; set; } public Author Owner { get; set; } = default!; public ICollection<Author> Contributors { get; } }
ساختار ابتدایی گروههای مقالات بلاگ
namespace MinimalBlog.Domain.Model; public class Category { public Category() { Articles = new List<Article>(); } public int Id { get; set; } public string Name { get; set; } = default!; public string Description { get; set; } = default!; public ICollection<Article> Articles { get; set; } }
معرفی موجودیتهای تعریف شده به لایهی Dal
لایهی Dal جایی است که DbContext برنامه تعریف میشود و موجودیتها فوق توسط DbSetها در معرض دید EF-Core قرار میگیرند. به همین جهت ابتدا فایل MinimalBlog.Dal.csproj را به صورت زیر تغییر میدهیم:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net6.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <ProjectReference Include="..\MinimalBlog.Domain\MinimalBlog.Domain.csproj" /> </ItemGroup> <ItemGroup> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.2" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.2" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.2"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> </ItemGroup> </Project>
به علاوه تعاریفی مانند ImplicitUsings و Nullable را هم مشاهده میکنید که با توجه به استفادهی از فایل Directory.Build.props غیرضروری و تکراری هستند؛ چون این فایل مخصوص به همراه این تعاریف سراسری نیز هست.
سپس به پروژهی Dal، کلاس جدید MinimalBlogDbContext را به صورت زیر اضافه میکنیم تا مدلهای برنامه را در معرض دید EF-Core قرار دهد:
using Microsoft.EntityFrameworkCore; using MinimalBlog.Domain.Model; namespace MinimalBlog.Dal; public class MinimalBlogDbContext : DbContext { public MinimalBlogDbContext(DbContextOptions options) : base(options) { } public DbSet<Article> Articles { get; set; } = default!; public DbSet<Category> Categories { get; set; } = default!; public DbSet<Author> Authors { get; set; } = default!; public DbSet<Blog> Blogs { get; set; } = default!; }
ایجاد و اجرای Migrations
پس از تعریف MinimalBlogDbContext، اکنون نوبت به ایجاد کلاسهای Migrations و اجرای آنها جهت ایجاد بانک اطلاعاتی متناظر با مدلهای برنامه است. برای این منظور در ابتدا به پروژهی Api مراجعه کرده و فایل appsettings.json را به صورت زیر تکمیل میکنیم:
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*", "ConnectionStrings": { "Default": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=MinimalBlog;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False" } }
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>net6.0</TargetFramework> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> </PropertyGroup> <ItemGroup> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.2" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.2" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.2"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> </ItemGroup> <ItemGroup> <ProjectReference Include="..\MinimalBlog.Domain\MinimalBlog.Domain.csproj" /> <ProjectReference Include="..\MinimalBlog.Dal\MinimalBlog.Dal.csproj" /> </ItemGroup> </Project>
using Microsoft.EntityFrameworkCore; using MinimalBlog.Dal; var builder = WebApplication.CreateBuilder(args); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var connectionString = builder.Configuration.GetConnectionString("Default"); builder.Services.AddDbContext<MinimalBlogDbContext>(opt => opt.UseSqlServer(connectionString));
پس از این تنظیمات به پوشهی MinimalBlog.Dal وارد شده و فایل _01-add_migrations.cmd را اجرا میکنیم (این فایل به همراه پیوست قسمت اول، ارائه شدهاست). محتوای این فایل به صورت زیر است:
For /f "tokens=2-4 delims=/ " %%a in ('date /t') do (set mydate=%%c_%%a_%%b) For /f "tokens=1-2 delims=/:" %%a in ("%TIME: =0%") do (set mytime=%%a%%b) dotnet tool update --global dotnet-ef --version 6.0.2 dotnet build dotnet ef migrations --startup-project ../MinimalBlog.Api/ add V%mydate%_%mytime% --context MinimalBlogDbContext pause
البته چون کدهای تولید شدهی به صورت خودکار الزاما با Roslyn analyzers برنامه سازگاری ندارند، آنها را توسط فایل مخصوص editorconfig. قرار گرفتهی در پوشهی MinimalBlog.Dal\Migrations، از لیست آنالیزهای برنامه خارج میکنیم. محتوای این فایل ویژه به صورت زیر است:
[*.cs] generated_code = true
پس از ایجاد کلاسهای Migration، اکنون نوبت به اجرای آنها بر روی بانک اطلاعاتی است که در رشتهی اتصالی مشخص کردیم. برای اینکار فایل MinimalBlog.Dal\_02-update_db.cmd را اجرا میکنیم که چنین محتویاتی دارد:
dotnet tool update --global dotnet-ef --version 6.0.2 dotnet build dotnet ef --startup-project ../MinimalBlog.Api/ database update --context MinimalBlogDbContext pause