شروع به کار با EF Core 1.0 - قسمت 4 - کار با بانک‌های اطلاعاتی از پیش موجود
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: شش دقیقه

روش کار پیش فرض با EF Core همان روش Code First است. ابتدا کلاس‌ها و روابط بین آن‌ها را تنظیم می‌کنید. سپس با استفاده از ابزارهای Migrations، بانک اطلاعاتی متناظری تولید خواهد شد. این ابزارها به همراه روشی برای مهندسی معکوس ساختار یک بانک اطلاعاتی از پیش موجود، به روش Code First نیز هستند که در ادامه جزئیات آن‌را بررسی خواهیم کرد. بنابراین اگر به دنبال روش کاری Database first با EF Core هستید، در اینجا نیز امکان آن وجود دارد.


تهیه یک بانک اطلاعاتی نمونه

برای نمایش امکانات کار با روش Database first، نیاز است یک بانک اطلاعاتی را به صورت مستقل و متداولی ایجاد کنیم. به همین جهت اسکریپت SQL ذیل را توسط Management studio اجرا کنید تا بانک اطلاعاتی BloggingCore2016، به همراه دو جدول به هم وابسته، در آن ایجاد شوند:
CREATE DATABASE [BloggingCore2016]
GO

USE [BloggingCore2016]
GO

CREATE TABLE [Blog] (
    [BlogId] int NOT NULL IDENTITY,
    [Url] nvarchar(max) NOT NULL,
    CONSTRAINT [PK_Blog] PRIMARY KEY ([BlogId])
);
GO

CREATE TABLE [Post] (
    [PostId] int NOT NULL IDENTITY,
    [BlogId] int NOT NULL,
    [Content] nvarchar(max),
    [Title] nvarchar(max),
    CONSTRAINT [PK_Post] PRIMARY KEY ([PostId]),
    CONSTRAINT [FK_Post_Blog_BlogId] FOREIGN KEY ([BlogId]) REFERENCES [Blog] ([BlogId]) ON DELETE CASCADE
);
GO

INSERT INTO [Blog] (Url) VALUES 
('https://www.dntips.ir/'), 
('http://blogs.msdn.com/dotnet'), 
('http://blogs.msdn.com/webdev'), 
('http://blogs.msdn.com/visualstudio')
GO



پیشنیازهای مهندسی معکوس ساختار بانک اطلاعاتی در EF Core

در قسمت اول در حین بررسی «برپایی تنظیمات اولیه‌ی EF Core 1.0 در یک برنامه‌ی ASP.NET Core 1.0»، چهار مدخل جدید را به فایل project.json برنامه اضافه کردیم. مدخل جدید Microsoft.EntityFrameworkCore.Tools که به قسمت tools آن اضافه شد، پیشنیاز اصلی کار با EF Core Migrations است. همچنین وجود مدخل Microsoft.EntityFrameworkCore.SqlServer.Design برای تدارک امکانات مهندسی معکوس ساختار یک بانک اطلاعاتی SQL Server ضروری است.


تبدیل ساختار دیتابیس BloggingCore2016 به کدهای معادل EF Core آن

پس از فعال سازی ابزارهای خط فرمان EF Core، به پوشه‌ی اصلی پروژه مراجعه کرده، کلید shift را نگه دارید. سپس کلیک راست کرده و گزینه‌ی Open command window here را انتخاب کنید تا خط فرمان از این پوشه آغاز شود. در ادامه دستور ذیل را صادر کنید:
 dotnet ef dbcontext scaffold "Data Source=(local);Initial Catalog=BloggingCore2016;Integrated Security = true" Microsoft.EntityFrameworkCore.SqlServer -o Entities --context MyDBDataContext --verbose


اجرا این دستور سبب اتصال به رشته‌ی اتصالی ذکر شده که به بانک اطلاعاتی BloggingCore2016 اشاره می‌کند، می‌شود. سپس پروایدر مدنظر ذکر شده‌است. سوئیچ o محل درج فایل‌های نهایی را مشخص می‌کند. برای مثال در اینجا فایل‌های نهایی مهندسی معکوس شده در پوشه‌ی Entities درج می‌شوند (تصویر فوق). همچنین در اینجا امکان ذکر فایل context تولیدی نیز وجود دارد. اگر علاقمند باشید تا تمام ریز جزئیات این عملیات را نیز مشاهده کنید، می‌توانید پارامتر اختیاری verbose را نیز به انتهای دستور اضافه نمائید.

بقیه مراحل کار با این فایل‌های تولید شده، با نکاتی که تاکنون عنوان شده‌اند یکی است. برای مثال اگر می‌خواهید رشته‌ی اتصالی پیش فرض را از این Context تولید شده خارج کنید:
    public partial class MyDBDataContext : DbContext
    {
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(@"Data Source=(local);Initial Catalog=BloggingCore2016;Integrated Security = true");
        }
روش کار دقیقا همانی است که در مطلب «شروع به کار با EF Core 1.0 - قسمت 1 - برپایی تنظیمات اولیه» بررسی شد.


بررسی پارامترهای دیگر ابزار مهندسی معکوس به Code First

اگر دستور dotnet ef dbcontext scaffold --help را صادر کنیم، خروجی راهنمای ذیل را می‌توان مشاهده کرد:
 Usage: dotnet ef dbcontext scaffold [arguments] [options]
Arguments:
  [connection]  The connection string of the database
  [provider] The provider to use. For example, Microsoft.EntityFrameworkCore.SqlServer
Options:
  -a|--data-annotations   Use DataAnnotation attributes to configure the model where possible. If omitted, the output code will use only the fluent API.
  -c|--context <name> Name of the generated DbContext class.
  -f|--force Force scaffolding to overwrite existing files. Otherwise, the code will only proceed if no output files would be overwritten.
  -o|--output-dir <path> Directory of the project where the classes should be output. If omitted, the top-level project directory is used.
  --schema <schema> Selects a schema for which to generate classes.
  -t|--table <schema.table> Selects a table for which to generate classes.
  -e|--environment <environment>  The environment to use. If omitted, "Development" is used.
  -h|--help   Show help information
  -v|--verbose   Enable verbose output
نکات تکمیلی مهمی را که از آن می‌توان استخراج کرد به این شرح هستند:
- حالت پیش فرض تنظیمات روابط مدل‌ها در این روش، حالت استفاده از Fluent API است. اگر می‌خواهید آن‌را به حالت استفاده‌ی از Data Annotations تغییر دهید، پارامتر a- و یا data-annotations-- را در دستور نهایی ذکر کنید.
- حالت پیش فرض تولید فایل‌های نهایی این روش، عدم بازنویسی فایل‌های موجود است. اگر می‌خواهید پس از تغییر بانک اطلاعاتی، مجددا این فایل‌ها را از صفر تولید کنید، پارامتر f- و یا force- را در دستور نهایی ذکر کنید.

بنابراین اگر می‌خواهید هربار فایل‌های نهایی را بازنویسی کنید و همچنین روش کار با Data Annotations را ترجیح می‌دهید، دستور نهایی، شکل زیر را پیدا خواهد کرد:
 dotnet ef dbcontext scaffold "Data Source=(local);Initial Catalog=BloggingCore2016;Integrated Security = true" Microsoft.EntityFrameworkCore.SqlServer -o Entities --context MyDBDataContext --verbose --force --data-annotations


کار با یک بانک اطلاعاتی موجود، با روش مهاجرت‌های Code First

فرض کنید می‌خواهید از یک بانک اطلاعاتی از پیش موجود EF 6.x (یا هر بانک اطلاعاتی از پیش موجود دیگری)، به روش پیش فرض EF Core استفاده کنید. برای این منظور:
 - ابتدا جدول migration history قدیمی آن‌را حذف کنید؛ چون ساختار آن با EF Core یکی نیست.
 - سپس با استفاده از دستور dotnet ef dbcontext scaffold فوق، معادل کلاس‌ها، روابط و Context سازگار با EF Core آن‌را تولید کنید.
 - در ادامه رشته‌ی اتصالی پیش فرض آن‌را از کلاس Context تولیدی خارج کرده و از یکی از روش‌های مطرح شده‌ی در مطلب «شروع به کار با EF Core 1.0 - قسمت 1 - برپایی تنظیمات اولیه» استفاده کنید.
 - سپس نیاز است این Context جدید را توسط متد services.AddDbContext به لیست سرویس‌های برنامه اضافه کنید. این مورد نیز در قسمت اول بررسی شده‌است.
 - مرحله‌ی بعد، افزودن جدول __EFMigrationsHistory جدید EF Core، به این بانک اطلاعاتی است. برای این منظور به روش متداول فعال کردن مهاجرت‌ها، دستور ذیل را صادر کنید:
dotnet ef migrations add InitialDatabase
تا اینجا کلاس آغازین مهاجرت‌ها تولید می‌شود. فایل آن‌را گشوده و محتوای متدهای Up و Down آن‌را خالی کنید:
using Microsoft.EntityFrameworkCore.Migrations;

namespace Core1RtmEmptyTest.DataLayer.Migrations
{
    public partial class InitialDatabase : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
        }
    }
}
متدهای up و down را از این جهت خالی می‌کنیم که علاقمند نیستیم تا ساختاری در بانک اطلاعاتی تشکیل شود و یا تغییر کند (چون این ساختار هم اکنون موجود است).
سپس دستور به روز رسانی بانک اطلاعاتی را صادر کنید:
dotnet ef database update
کار این دستور در اینجا با توجه به خالی بودن متدهای up و down، صرفا ساخت جدول مخصوص __EFMigrationsHistory در بانک اطلاعاتی است؛ بدون تغییری در جداول موجود آن.
پس از این مرحله، روش کار، Code first خواهد بود. برای مثال خاصیتی را به کلاسی اضافه می‌کنید و سپس دو دستور ذیل را صادر خواهید کرد که در آن v2 یک نام دلخواه است:
dotnet ef migrations add v2
dotnet ef database update
  • #
    ‫۵ سال و ۶ ماه قبل، سه‌شنبه ۲۸ اسفند ۱۳۹۷، ساعت ۱۵:۲۱
    سلام. من با ef core 3.0  دیتابیس خودم رو با دستور زیر مهاجرت دادم
    Scaffold-DbContext "connectionstring" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Entities -DataAnnotations
    چون من فیلدهایی از نوع DBGeography کلاس  Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite    رو به پروژه ام  اضافه کردم. وقتی که میخوام add-migration میزنم خطای زیر رو دریافت می‌کنم.
    UseNetTopologySuite requires AddEntityFrameworkSqlServerNetTopologySuite to be called on the internal service provider used.
    • #
      ‫۵ سال و ۶ ماه قبل، سه‌شنبه ۲۸ اسفند ۱۳۹۷، ساعت ۱۶:۱۴
      این خطا صرفا به معنای عدم تطابق شماره نگارش بسته‌ی نصب شده در پروژه با آخرین شماره نگارش SDK نصب شده‌ی بر روی سیستم است. در نگارش الف، ابزار Migration از قابلیتی استفاده کرده که در نگارش ب آن از طرف خودشان ممنوع اعلام شده (برای تیم توسعه دهنده) و یا برعکس عنوان شده که چنین سرویسی را باید به صورت داخلی فراخوانی کنند (در کل هدف از این استثناء شما نیستید؛ خود تیم EF است):
      public class MyDesignTimeServices : IDesignTimeServices
      {
          public void ConfigureDesignTimeServices(IServiceCollection services)
              => services.AddEntityFrameworkSqlServerNetTopologySuite();
      }
  • #
    ‫۴ سال و ۸ ماه قبل، دوشنبه ۲ دی ۱۳۹۸، ساعت ۱۴:۲۸
    با سلام؛ سوالم اینجاست این برای حالتی هست که از قبل دیتابیس داشته باشیم و بخواهیم به codefirst  تبدیل کنیم؛ اما اگر بخواهیم از حالت codefirst  به حالت dbfirst  تبدیل کنیم، چطور؟
    • #
      ‫۴ سال و ۸ ماه قبل، دوشنبه ۲ دی ۱۳۹۸، ساعت ۱۴:۵۵
      - برای ایجاد بانک اطلاعاتی از روی کلاس‌ها و مدل‌های برنامه، نیاز به ()context.Database.Migrate خواهید داشت.
      - ضمنا مایکروسافت روش «db first» را خیلی وقت هست که کنار گذاشته؛ از زمان ارائه‌ی «Entity framework code-first». آگاهی از تاریخچه‌ی تغییرات علم و فناوری‌ها، سردرگمی شما را برای انتخاب آن‌ها کمتر می‌کند.
  • #
    ‫۱ سال قبل، چهارشنبه ۱۵ شهریور ۱۴۰۲، ساعت ۱۴:۲۳
    مهندسی معکوس انواع و اقسام بانک‌های اطلاعاتی از پیش‌موجود به کلاس‌های Context و موجودیت‌های EF Core Code First

    الف) SQL Server
    وابستگی‌های مورد نیاز در یک پروژه‌ی classlib فرضی:
    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
        <TargetFramework>net7.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
      </PropertyGroup>
    
      <ItemGroup>
        <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.10">
          <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
          <PrivateAssets>all</PrivateAssets>
        </PackageReference>
        <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.10" />
        <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.10">
          <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
          <PrivateAssets>all</PrivateAssets>
        </PackageReference>
      </ItemGroup>
    </Project>
    و همچنین نصب ابزارهای خط‌فرمان EF:
    dotnet tool update --global dotnet-ef --version 7.0.10
    سپس اجرای دستور زیر در ریشه‌ی پروژه:
    dotnet ef dbcontext scaffold "Data Source=(localdb)\mssqllocaldb;Initial Catalog=DbName;Encrypt=false;" Microsoft.EntityFrameworkCore.SqlServer -o Output -f

    ب) MySQL
    وابستگی‌های مورد نیاز در یک پروژه‌ی classlib فرضی:
    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
        <TargetFramework>net7.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
      </PropertyGroup>
    
      <ItemGroup>
        <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.10">
          <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
          <PrivateAssets>all</PrivateAssets>
        </PackageReference>
        <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="7.0.0" />
        <PackageReference Include="Pomelo.EntityFrameworkCore.MySql.Design" Version="1.1.2" />
      </ItemGroup>
    </Project>
     و همچنین نصب ابزارهای خط‌فرمان EF:
    dotnet tool update --global dotnet-ef --version 7.0.10
    سپس اجرای دستور زیر در ریشه‌ی پروژه:
    dotnet ef dbcontext scaffold "server=localhost;port=3306;user=root;password=MyPass;database=MyDbName;TreatTinyAsBoolean=true;AllowZeroDateTime=true;ConvertZeroDateTime=true;" Pomelo.EntityFrameworkCore.MySql -o Output -f

    ج) Postgres 
    وابستگی‌های مورد نیاز در یک پروژه‌ی classlib فرضی:
    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
        <TargetFramework>net7.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
      </PropertyGroup>
    
      <ItemGroup>
        <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.10">
          <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
          <PrivateAssets>all</PrivateAssets>
        </PackageReference>
        <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.10">
          <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
          <PrivateAssets>all</PrivateAssets>
        </PackageReference>
        <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.4"/>
      </ItemGroup>
    </Project>
    و همچنین نصب ابزارهای خط‌فرمان EF:
    dotnet tool update --global dotnet-ef --version 7.0.10
    سپس اجرای دستور زیر در ریشه‌ی پروژه:
    dotnet ef dbcontext scaffold "User ID=Vahid;Password=MyPass;Host=localhost;Port=5432;Database=MyDbName;Pooling=true;" Npgsql.EntityFrameworkCore.PostgreSQL -o Output -f

    د) SQLite
    وابستگی‌های مورد نیاز در یک پروژه‌ی classlib فرضی: 
    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
        <TargetFramework>net7.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
      </PropertyGroup>
    
      <ItemGroup>
        <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.10">
          <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
          <PrivateAssets>all</PrivateAssets>
        </PackageReference>
        <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.10" />
        <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="7.0.10" />
        <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.10">
          <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
          <PrivateAssets>all</PrivateAssets>
        </PackageReference>
      </ItemGroup>
    </Project>
     و همچنین نصب ابزارهای خط‌فرمان EF:
    dotnet tool update --global dotnet-ef --version 7.0.10
    سپس اجرای دستور زیر در ریشه‌ی پروژه: 
    dotnet ef dbcontext scaffold "Data Source=C:\\Path\\db.sqlite" Microsoft.EntityFrameworkCore.Sqlite -o Output