SQL is unusual is that data is not passively stored. Instead you use declarative SQL to specify the rules that underlie the data and its integrity. When used properly, constraints can avoid having to provide a lot of logic elsewhere. CHECK() and DEFAULT can do a lot to ensure that your data is correct
آینده توسعه برنامه های موبایل چیست؟
ایجاد مدلها و موجودیتهای برنامهی 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
کتابخانه imhere-angular-wizard
Imhere-Angular-wizard is a component that will make it easy for you to create wizards in your app. You can check a running example of the wizard Demo
This command allows cleaning up project and assembly references that have no actual usages in source code. You can apply this command on a project, solution folder, or the entire solution. Before deletion is complete, you will be able to see all references that are going to be removed and. if necessary, preserve the ones that you want to keep.
در این مطلب با توجه به سؤالات زیادی که در مورد صرفا نحوهی اجرای بدون خطای آن وجود داشت، ریز مراحل آنرا بررسی میکنیم.
پیشنیازهای توسعهی برنامه
- با توجه به استفاده از ویژگیهای C# 6 در این پروژه، حتما نیاز است برای کار و اجرای آن از VS 2015 استفاده کنید.
- همچنین این پروژه از قابلیت «فایل استریم» SQL Server استفاده میکند. بنابراین نیاز است نگارش متناسبی از SQL Server را پیشتر نصب کرده باشید (هر نگارشی بالاتر از SQL Server 2005).
- اگر از ReSharper استفاده میکنید، به صورت موقت آنرا به حالت تعلیق درآورید (منوی tools، گرینهی options و انتخاب resharper و سپس suspend کردن آن). این مورد سرعت بازیابی بستههای نیوگت را به شدت افزایش میدهد.
بازیابی وابستگیهای نیوگت پروژه
مرسوم نیست چند 10 مگابایت وابستگیهای پروژه را به صورت فایلهای باینری، به مخزن کدها ارسال کرد. از این جهت که نیوگت بر اساس مداخل فایلهای packages.config، قابلیت بازیابی و نصب خودکار آنها را دارد. بنابراین ابتدا package manger console را باز کنید؛ از طریق منوی Tools -> NuGet Package Manager -> Package Manager Console
همانطور که در تصویر مشاهده میکنید، نیوگت تشخیص دادهاست که بستههایی برای نصب وجود دارند. بنابراین بر روی دکمهی restore کلیک کنید تا کار دریافت و نصب خودکار این بستهها از اینترنت شروع شود. البته اگر پیشتر این بستهها را در پروژههای دیگری نصب کرده باشید، نیوگت از کش موجود در سیستم استفاده خواهد کرد و برای دریافت آنها به اینترنت مراجعه نمیکند. ولی در هر حال اتصال به اینترنت ضروری است.
پس از پایان کار بازیابی بستهها، یکبار کل Solution را Build کنید تا مطمئن شوید که تمام بستههای مورد نیاز به درستی بازیابی و نصب شدهاند (Ctrl+Shift+B و یا همان منوی Build و انتخاب گزینهی Build Solution).
تنظیمات رشته اتصالی بانک اطلاعاتی برنامه
پس از Build موفق کل Solution در مرحلهی قبل، اکنون نوبت به برپایی تنظیمات بانک اطلاعاتی برنامه است. برای این منظور فایل web.config ذیل را باز کنید:
Decision\src\Decision.Web\Web.config
یک چنین تنظیمی را مشاهده میکنید:
<connectionStrings> <clear /> <add name="DefaultConnection" connectionString="Data Source=.\sqlexpress;Initial Catalog=DecisionDb;Integrated Security = true;MultipleActiveResultSets=True;" providerName="System.Data.SqlClient" /> </connectionStrings>
<connectionStrings> <clear /> <add name="DefaultConnection" connectionString="Data Source=(local);Initial Catalog=DecisionDb;Integrated Security = true;MultipleActiveResultSets=True;" providerName="System.Data.SqlClient" /> </connectionStrings>
در این حالت نیاز است بانک اطلاعاتی خالی DecisionDb را خودتان ایجاد کنید. علت آن به AutomaticMigrationsEnabled = false بر میگردد؛ که در ادامه توضیح داده شدهاست و همچنین وجود تنظیم ذیل در فایل Decision\src\Decision.Web\App_Start\ApplicationStart.cs
Database.SetInitializer<ApplicationDbContext>(null);
ایجاد بانک اطلاعاتی برنامه و تنظیمات آن
پس از آن، نوبت به ایجاد بانک اطلاعاتی برنامه است. چون این برنامه از EF Code first استفاده میکند، قادر است بانک اطلاعاتی ذکر شدهی در Initial Catalog فوق را به صورت خودکار ایجاد کند (با تمام جداول، روابط و تنظیمات آنها). این اطلاعات هم از پروژهی Decision.DataLayer و پوشهی Migrations آن تامین میشوند.
اگر به فایل Decision\src\Decision.DataLayer\Migrations\201602072159421_Initial.cs مراجعه کنید، یکسری تنظیمات دستی را هم علاوه بر کدهای خودکار EF، مشاهده خواهید کرد:
//. . . Sql("EXEC sp_configure filestream_access_level, 2"); Sql("RECONFIGURE", true); Sql("alter database DecisionDb Add FileGroup FileGroupApplicant contains FileStream", true); Sql("alter database DecisionDb add file ( name = 'ApplicantDocuements' , filename = 'C:\\FileStream\\ApplicantDocuements') to filegroup FileGroupApplicant", true); //. . .
بنابراین نیاز است در درایور C، پوشهی خالی FileStream از پیش تهیه شده باشد (نیازی به ایجاد پوشهی ApplicantDocuements نیست و این پوشه به صورت خودکار ایجاد میشود).
و در فایل Decision\src\Decision.DataLayer\Migrations\Configuration.cs مشخص شدهاست که AutomaticMigrationsEnabled = false. به این معنا که تنظیمات فوق به صورت خودکار به بانک اطلاعاتی اعمال نشده و باید چند دستور ذیل را به صورت دستی صادر کنیم:
الف) ابتدا package manager console را مجددا باز کنید و در اینجا default project را بر روی Decision.DataLayer قرار دهید. از این جهت که قرار است اطلاعات migration را از این پروژه دریافت کنیم:
در غیراینصورت پیام خطای No migrations configuration type was found in the assembly را دریافت خواهید کرد.
ب) سپس دستور ذیل را صادر کنید (با این فرض که بانک اطلاعاتی خالی DecisionDb ذکر شدهی در قسمت قبل را پیشتر ایجاد کردهاید):
PM> Update-Database -Verbose -ConnectionStringName "DefaultConnection" -StartUpProjectName "Decision.Web"
من در این حالت پیام خطای Update-Database : The term 'Update-Database' is not recognized as the name of a cmdlet را دریافت کردم.
راه حل: یکبار ویژوال استودیو را بسته و مجددا باز کنید تا کار نصب بستهها و بارگذاری تمام وابستگیهای آنها به درستی صورت گیرد. این خطا به این معنا است که هرچند NuGet کار نصب EF را انجام دادهاست، اما هنوز اسکریپتهای پاورشل آن که دستوراتی مانند Update-Database را اجرا میکنند، بارگذاری نشدهاند. راه حل آن بستن و اجرای مجدد ویژوال استودیو است.
پس از اجرای مجدد ویژوال استودیو و انتخاب default project صحیح (مطابق تصویر فوق)، مجددا دستور Update-Database فوق را صادر کنید (با پارامترهای ویژهی آن).
با صدور این دستور، پیام خطای ذیل را دریافت کردم:
The Entity Framework provider type 'System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework' registered in the application config file for the ADO.NET provider with invariant name 'System.Data.SqlClient' could not be loaded.
PM> Update-Package -Reinstall "EntityFramework" -ProjectName "Decision.DataLayer"
اینبار دستور update-database فوق (با پارامترهای ویژهی آن) بدون مشکل اجرا شد و بانک اطلاعاتی مربوطه تشکیل گردید.
اکنون برنامه قابل اجرا است و در این حالت است که میتوان دکمهی F5 را جهت اجرای برنامه فشرد. البته در این حالت بر روی پروژهی Decision.Web کلیک راست کرده و گزینهی set as startup project را نیز انتخاب کنید و سپس F5:
لطفا سؤالاتی را که مرتبط با «راه اندازی» این پروژه نیستند، در قسمت بازخوردهای اختصاصی آن مطرح کنید.
CSS3 (~2009-2012):
Level 3 CSS specs as defined by the CSSWG. (immutable)
CSS4 (~2013-2018):
Essential features that were not part of CSS3 but are already a fundamental part of CSS.
CSS5 (~2019-2024):
Newer features whose adoption is steadily growing.
CSS6 (~2025+):
Early-stage features that are planned for future CSS.
اندکی به روز رسانی
پیغم خطا در RapidShare برای Download کردن این فایل:
You want to download the following file:
http://rapidshare.com/files/350592779/blog3.chm | 6836 KB
Currently a lot of users are downloading files. Please try again in 2 minutes or become a Premium member
Please note, the server is not going to check again within the next 2 minutes if downloading is possible again. To provide a fair platform, all user get the same options. Your last attempt was 39 seconds ago.