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

پس از برپایی تنظیمات اولیه‌ی کار با EF Core در ASP.NET Core، اکنون نوبت به تبدیل کلاس Person، به جدول معادل آن در بانک اطلاعاتی برنامه است. در EF Core نیز همانند EF Code First 6.x، برای انجام یک چنین اعمالی از مفهومی به نام Migrations استفاده می‌شود که در ادامه به آن خواهیم پرداخت.


پیشنیازهای کار با EF Core Migrations

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


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

پس از تکمیل پیشنیازهای کار با EF Core، از طریق خط فرمان به پوشه‌ی جاری پروژه وارد شده و دستور dotnet ef را صادر کنید.
یک نکته: در ویندوز اگر در پوشه‌ای، کلید shift را نگه دارید و در آن پوشه کلیک راست کنید، در منوی باز شده، گزینه‌ی جدیدی را به نام Open command window here مشاهده خواهید کرد که می‌تواند به سرعت خط فرمان را از پوشه‌ی جاری شروع کند.

خروجی صدور فرمان dotnet ef را در ذیل مشاهده می‌کنید:
D:\Prog\1395\Core1RtmEmptyTest\src\Core1RtmEmptyTest>dotnet ef
                     _/\__
               ---==/    \\
         ___  ___   |.    \|\
        | __|| __|  |  )   \\\
        | _| | _|   \_/ |  //|\\
        |___||_|       /   \\\/\\
Entity Framework .NET Core CLI Commands 1.0.0-preview2-21431
Usage: dotnet ef [options] [command]
Options:
  -h|--help                      Show help information
  -v|--verbose                   Enable verbose output
  --version                      Show version information
  --assembly <ASSEMBLY>          The assembly file to load.
  --startup-assembly <ASSEMBLY>  The assembly file containing the startup class.
  --data-dir <DIR>               The folder used as the data directory (defaults to current working directory).
  --project-dir <DIR>            The folder used as the project directory (defaults to current working directory).
  --content-root-path <DIR>      The folder used as the content root path for the application (defaults to application base directory).
  --root-namespace <NAMESPACE>   The root namespace of the target project (defaults to the project assembly name).
Commands:
  database    Commands to manage your database
  dbcontext   Commands to manage your DbContext types
  migrations  Commands to manage your migrations
Use "dotnet ef [command] --help" for more information about a command.
در قسمت Commands آن در انتهای لیست، از فرمان migrations آن استفاده خواهیم کرد. برای این منظور در همین پوشه‌ی جاری، دستور ذیل را صادر کنید:
 D:\Prog\1395\Core1RtmEmptyTest\src\Core1RtmEmptyTest>dotnet ef migrations add InitialDatabase
دستورات migrations با dotnet ef migrations شروع شده و سپس یک سری پارامتر را دریافت می‌کنند برای مثال در اینجا سوئیچ add، به همراه یک نام دلخواه ذکر شده‌است (نام این مرحله را InitialDatabase گذاشته‌ایم). پس از فراخوانی این دستور، اگر به Solution explorer مراجعه کنید، پوشه‌ی جدید Migrations، قابل مشاهده است:


نام دلخواه InitialDatabase را در انتهای نام فایل 13950526050417_InitialDatabase مشاهده می‌کنید.
اگر قصد حذف این مرحله را داشته باشیم، می‌توان دستور dotnet ef migrations remove را مجددا صادر کرد.

فایل 13950526050417_InitialDatabase به همراه کلاسی است که در آن دو متد Up و Down قابل مشاهده هستند. متد Up نحوه‌ی ایجاد جدول جدیدی را از کلاس Person بیان می‌کند و متد Down نحوه‌ی Drop این جدول را پیاده سازی کرده‌است.
فایل ApplicationDbContextModelSnapshot.cs دارای کلاسی است که خلاصه‌ای از تعاریف موجودیت‌های ذکر شده‌ی در DB Context برنامه را به همراه دارد و تفسیر آن‌ها را از دیدگاه  EF در اینجا می‌توان مشاهده کرد.

پس از مرحله‌ی افزودن migrations، نوبت به اعمال آن به بانک اطلاعاتی است. تا اینجا EF تنها متدهای Up و Down مربوط به ساخت و حذف ساختار جداول را ایجاد کرده‌است. اما هنوز آن‌ها را به بانک اطلاعاتی برنامه اعمال نکرده‌است. برای اینکار در پوشه‌ی جاری دستور ذیل را صادر کنید:
 D:\Prog\1395\Core1RtmEmptyTest\src\Core1RtmEmptyTest>dotnet ef database update
Applying migration '13950526050417_InitialDatabase'.
Done.
همانطور که ملاحظه می‌کنید، دستور dotnet ef database update سبب اعمال اطلاعات فایل 13950526050417_InitialDatabase به بانک اطلاعاتی شده‌است.
اکنون اگر به لیست بانک‌های اطلاعاتی مراجعه کنیم، بانک اطلاعاتی جدید TestDbCore2016 را به همراه جدول متناظر کلاس Person می‌توان مشاهده کرد:


در اینجا جدول دیگری به نام __EFMigrationsHistory نیز قابل مشاهده‌است که کار آن ذخیره سازی وضعیت فعلی Migrations در بانک اطلاعاتی، جهت مقایسه‌های آتی است. این جدول صرفا توسط ابزارهای EF استفاده می‌شود و نباید به صورت مستقیم تغییری در آن ایجاد کنید.


مقدار دهی اولیه‌ی جداول بانک‌های اطلاعاتی در EF Core

در همین حالت اگر کنترلر TestDB مطرح شده‌ی در انتهای بحث قسمت قبل را اجرا کنیم، به این استثناء خواهیم رسید:


این تصویر بدین معنا است که کار Migrations موفقیت آمیز بوده‌است و اینبار امکان اتصال و کار با بانک اطلاعاتی وجود دارد، اما این جدول حاوی اطلاعات اولیه‌ای برای نمایش نیست.
در نگارش قبلی EF Code First، امکانات Migrations به همراه یک متد Seed نیز بود که توسط آن کار مقدار دهی اولیه‌ی جداول را می‌توان انجام داد (زمانیکه جدولی ایجاد می‌شود، در همان هنگام، چند رکورد خاص نیز به آن اضافه شوند. برای مثال به جدول کاربران، رکورد اولین کاربر یا همان Admin اضافه شود). این متد در EF Core 1.0 وجود ندارد.
برای این منظور کلاس جدیدی را به نام ApplicationDbContextSeedData به همان پوشه‌ی جدید Migrations اضافه کنید؛ با این محتوا:
using System.Collections.Generic;
using System.Linq;
using Core1RtmEmptyTest.Entities;
using Microsoft.Extensions.DependencyInjection;

namespace Core1RtmEmptyTest.Migrations
{
    public static class ApplicationDbContextSeedData
    {
        public static void SeedData(this IServiceScopeFactory scopeFactory)
        {
            using (var serviceScope = scopeFactory.CreateScope())
            {
                var context = serviceScope.ServiceProvider.GetService<ApplicationDbContext>();
                if (!context.Persons.Any())
                {
                    var persons = new List<Person>
                    {
                        new Person
                        {
                            FirstName = "Admin",
                            LastName = "User"
                        }
                    };
                    context.AddRange(persons);
                    context.SaveChanges();
                }
            }
        }
    }
}
و سپس نحوه‌ی فراخوانی آن در متد Configure کلاس آغازین برنامه به صورت زیر است:
public void Configure(IServiceScopeFactory scopeFactory)
{
    scopeFactory.SeedData();
به همراه این تغییر در نحوه‌ی معرفی Db Context برنامه:
public void ConfigureServices(IServiceCollection services)
{
   services.AddDbContext<ApplicationDbContext>(ServiceLifetime.Scoped);
توضیحات:
- برای پیاده سازی الگوی واحد کار، اولین قدم، مشخص سازی طول عمر Db Context برنامه است. برای اینکه تنها یک Context در طول یک درخواست وهله سازی شود، نیاز است به نحو صریحی طول عمر آن‌را به حالت Scoped تنظیم کرد. متد AddDbContext دارای پارامتری است که این طول عمر را دریافت می‌کند. بنابراین در اینجا ServiceLifetime.Scoped ذکر شده‌است. همچنین در این مثال از نمونه‌ای که IConfigurationRoot به سازنده‌ی کلاس ApplicationDbContext تزریق شده (نکته‌ی انتهای بحث قسمت قبل)، استفاده شده‌است. به همین جهت تنظیمات options آن‌را ملاحظه نمی‌کنید.
- مرحله‌ی بعد نحوه‌ی دسترسی به این سرویس ثبت شده در یک کلاس static دارای متدی الحاقی است. در اینجا دیگر دسترسی مستقیمی به تزریق وابستگی‌ها نداریم و باید کار را با  IServiceScopeFactory شروع کنیم. در اینجا می‌توانیم به صورت دستی یک Scope را ایجاد کرده، سپس توسط ServiceProvider آن، به سرویس ApplicationDbContext دسترسی پیدا کنیم و در ادامه از آن به نحو متداولی استفاده نمائیم. IServiceScopeFactory جزو سرویس‌های توکار ASP.NET Core است و در صورت ذکر آن به عنوان پارامتر جدیدی در متد Configure، به صورت خودکار وهله سازی شده و در اختیار ما قرار می‌گیرد.
- نکته‌ی مهمی که در اینجا بکار رفته‌است، ایجاد Scope و dispose خودکار آن توسط عبارت using است. باید دقت داشت که ایجاد Scope و تخریب آن به صورت خودکار در ابتدا و انتهای درخواست‌ها توسط ASP.NET Core انجام می‌شود. اما چون شروع کار ما از متد Configure است، در اینجا خارج از Scope قرار داریم و باید مدیریت ایجاد و تخریب آن‌را به صورت دستی انجام دهیم که نمونه‌ای از آن‌را در متد SeedData کلاس ApplicationDbContextSeedData ملاحظه می‌کنید. در اینجا Scope ایی ایجاد شده‌است. سپس داده‌های اولیه‌ی مدنظر به بانک اطلاعاتی اضافه گردیده و در آخر این Scope تخریب شده‌است.
- اگر کار ایجاد و تخریب scope، به نحوی که مشخص شده‌است انجام نگیرد، طول عمر درخواستی خارج از Scope، همواره Singleton خواهد بود. چون خارج از طول عمر درخواست جاری قرار داریم و هنوز کار به سرویس دهی درخواست‌ها نرسیده‌است. بنابراین مدیریت Scopeها هنوز شروع نشده‌است و باید به صورت دستی انجام شود.

در این حالت اگر برنامه را اجرا کنیم، این خروجی قابل مشاهده است:


که به معنای کار کردن متد SeedData و ثبت اطلاعات اولیه‌ای در بانک اطلاعاتی است.


اعمال تغییرات به مدل‌های برنامه و به روز رسانی ساختار بانک اطلاعاتی

فرض کنید به کلاس Person قسمت قبل، خاصیت Age را هم اضافه کرده‌ایم:
namespace Core1RtmEmptyTest.Entities
{
    public class Person
    {
        public int PersonId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }

        public int Age { get; set; }
    }
}
در این حالت اگر برنامه را اجرا کنیم، به استثنای ذیل خواهیم رسید:
 An unhandled exception occurred while processing the request.
SqlException: Invalid column name 'Age'.
برای رفع این مشکل نیاز است مجددا مراحل Migrations را اجرا کرد:
D:\Prog\1395\Core1RtmEmptyTest\src\Core1RtmEmptyTest>dotnet ef migrations add v2
D:\Prog\1395\Core1RtmEmptyTest\src\Core1RtmEmptyTest>dotnet ef database update
در اینجا همان دستورات قبل را مجددا اجرا می‌کنیم. با این تفاوت که اینبار نام دلخواه این مرحله را مثلا v2، به معنای نگارش دوم وارد کرده‌ایم.
با اجرا این دستورات، فایل جدید 13950526073248_v2 به پوشه‌ی Migrations اضافه می‌شود. این فایل حاوی نحوه‌ی به روز رسانی بانک اطلاعاتی، بر اساس خاصیت جدید Age است. سپس با اجرای دستور dotnet ef database update، کار به روز رسانی بانک اطلاعاتی بر اساس مرحله‌ی v2 انجام می‌شود.


بنابراین هر بار که تغییری را در مدل‌های خود ایجاد می‌کنید، یکبار باید کلاس مهاجرت آن‌را ایجاد کنید و سپس آن‌را به بانک اطلاعاتی اعمال نمائید.


تهیه اسکریپت تغییرات بجای اعمال تغییرات توسط ابزارهای EF

شاید علاقمند باشید که پیش از اعمال تغییرات به بانک اطلاعاتی، یک اسکریپت SQL از آن تهیه کنید (جهت مطالعه و یا اعمال دستی آن توسط خودتان). برای اینکار می‌توانید دستور ذیل را در پوشه‌ی جاری پروژه اجرا کنید:
 D:\Prog\1395\Core1RtmEmptyTest\src\Core1RtmEmptyTest>dotnet ef migrations script -o v2.sql
در این حالت اسکریپت SQL تغییرات، در فایلی به نام v2.sql، در ریشه‌ی جاری پروژه تولید می‌شود.


تغییرات ساختار جدول __EFMigrationsHistory در EF Core 1.0


در EF 6.x، ساختار اطلاعات جدول نگهداری تاریخچه‌ی تغییرات، بسیار پیچیده بود و شامل رشته‌ای gzip شده‌ی حاوی یک snapshot از کل ساختار دیتابیس در هر مرحله‌ی migration بود. در این نگارش، این snapshot حذف شده‌است و بجای آن فایل ApplicationDbContextModelSnapshot.cs را مشاهده می‌کنید (تنها یک snapshot به ازای کل context برنامه). همچنین در اینجا کاملا مشخص است که چه مراحلی به بانک اطلاعاتی اعمال شده‌اند و دیگر خبری از رشته‌ی gzip شده‌ی قبلی نیست (تصویر فوق).

در شکل زیر ساختار قبلی این جدول را در EF 6.x مشاهده می‌کنید. در EF 6.x حتی فضای نام کلاس‌های موجودیت‌های برنامه هم مهم هستند و در صورت تغییر، مشکل ایجاد می‌شود:



مهاجرت خودکار از EF Core حذف شده‌است

در EF 6.x در کنار کلاس Db Context یک کلاس Configuration هم وجود داشت که برای مثال امکان چنین تعریفی در آن میسر هست:
public Configuration()
{
   AutomaticMigrationsEnabled = true;
}
کار آن مهاجرت خودکار اطلاعات context به بانک اطلاعاتی بود؛ بدون نیازی به استفاده از دستورات خط فرمان مرتبط. تمام این موارد از EF Core حذف شده‌اند و علت آن‌را می‌توانید در توضیحات یکی از اعضای تیم EF Core در اینجا مطالعه کنید و خلاصه‌ی آن به این شرح است:
با حذف مهاجرت خودکار:
- دیگر نیازی نیست تا model snapshots در بانک اطلاعاتی ذخیره شوند (همان ساده شدن ساختار جدول ذخیره سازی تاریخچه‌ی مهاجرت‌های فوق).
- در حالت افزودن یک مرحله‌ی مهاجرت، دیگر نیازی به کوئری گرفتن از بانک اطلاعاتی نخواهد بود (سرعت بیشتر).
- می‌توان چندین مرحله‌ی مهاجرت را افزود بدون اینکه الزاما مجبور به اعمال آن‌ها به بانک اطلاعاتی باشیم.
- کاهش کدهای مدیریت ساختار بانک اطلاعاتی.
- تیم‌ها برای یکی کردن تغییرات خود مشکلی نخواهند داشت چون دیگر snapshot مدل‌ها در جدول __EFMigrationsHistory ذخیره نمی‌شود.

بنابراین در EF Core می‌توان مهاجرت v1 را اضافه کرد. سپس تغییراتی را در کدها اعمال کرد. در ادامه مهاجرت v2 را تولید کرد و در آخر کار اعمال یکجای این‌ها را به بانک اطلاعاتی انجام داد.

هرچند در اینجا اگر می‌خواهید مرحله‌ی اجرای دستور dotnet ef database update را حذف کنید، می‌توانید از کدهای ذیل نیز استفاده نمائید:
using Core1RtmEmptyTest.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;

namespace Core1RtmEmptyTest.Migrations
{
    public static class DbInitialization
    {
        public static void Initialize(this IServiceScopeFactory scopeFactory)
        {
            using (var serviceScope = scopeFactory.CreateScope())
            {
                var context = serviceScope.ServiceProvider.GetService<ApplicationDbContext>();
                // Applies any pending migrations for the context to the database.
                // Will create the database if it does not already exist.
                context.Database.Migrate();
            }
        }
    }
}
روش فراخوانی آن نیز همانند روش فراخوانی متد SeedData است که پیشتر بحث شد.
کار متد Migrate، ایجاد بانک اطلاعاتی در صورت عدم وجود و سپس اعمال تمام مراحل migration ایی است که در جدول __EFMigrationsHistory ثبت نشده‌اند (دقیقا همان کار دستور dotnet ef database update را انجام می‌دهد).


تفاوت متد Database.EnsureCreated با متد Database.Migrate

اگر به متدهای context.Database دقت کنید، یکی از آن‌ها EnsureCreated نام دارد. این متد نیز سبب تولید بانک اطلاعاتی بر اساس ساختار Context برنامه می‌شود. اما هدف آن صرفا استفاده‌ی از آن در آزمون‌های واحد سریع است. از این جهت که جدول __EFMigrationsHistory را تولید نمی‌کند (برخلاف متد Migrate). بنابراین بجز آزمون‌های واحد، در جای دیگری از آن استفاده نکنید چون به دلیل عدم تولید جدول __EFMigrationsHistory توسط آن، قابلیت استفاده‌ی از بانک اطلاعاتی تولید شده‌ی توسط آن با امکانات migrations وجود ندارد. در پایان آزمون واحد نیز می‌توان از متد EnsureDeleted برای حذف این بانک اطلاعاتی موقتی استفاده کرد.



در قسمت بعد، مطالب تکمیلی مهاجرت‌ها را بررسی خواهیم کرد. برای مثال چگونه می‌توان کلاس‌های موجودیت‌ها را به اسمبلی‌های دیگری منتقل کرد.
  • #
    ‫۸ سال قبل، چهارشنبه ۱۷ شهریور ۱۳۹۵، ساعت ۱۸:۲۰
    یک نکته‌ی تکمیلی
    اگر خواستید استراتژی آغازین DropCreateDatabaseAlways مربوط به EF 6.x را با EF Core شبیه سازی کنید، می‌توان یک چنین کدی را در سازنده‌ی کلاس Context نوشت (مفید برای انجام Integration Tests):
    public class SampleDBContext : DbContext
    {
        private static bool _created = false; 
        public SampleDBContext() 
        { 
            if (!_created) // DropCreateDatabaseAlways
            { 
                _created = true; 
                Database.EnsureDeleted(); 
                Database.EnsureCreated(); 
            } 
        }
  • #
    ‫۷ سال و ۲ ماه قبل، دوشنبه ۲۶ تیر ۱۳۹۶، ساعت ۲۱:۲۴
    من پروژه identitySample شما رو دانلود کردم و خودم رو یه پروژه دیگه بازنویسی کردم. ولی مشکلی که پیش اومد اینه که زمانیکه dotnet ef migrations add InitialDatabase  این دستور رو وارد میکنم، این خطا رو به من میده. مشکل از کجاست؟ باید چیکار کنم؟

  • #
    ‫۶ سال و ۱۱ ماه قبل، دوشنبه ۲۴ مهر ۱۳۹۶، ساعت ۲۳:۰۸
    اگر در پروژه از EF2 و netcore2 به همراه سیستم Identity استفاده شود تعاریف متدهای Configure  و ConfigureServices به چه صورت خواهد بود ؟
    با تشکر
    • #
      ‫۶ سال و ۱۱ ماه قبل، دوشنبه ۲۴ مهر ۱۳۹۶، ساعت ۲۳:۱۴
      پروژه‌ی DNTIdentity که دقیقا سفارشی سازی کامل ASP.NET Core Identity هست، به نگارش 2 ارتقاء داده شده‌است. همچنین عمده‌ی توضیحات آن هنوز هم برقرار هستند.
      • #
        ‫۶ سال و ۱۱ ماه قبل، سه‌شنبه ۲۵ مهر ۱۳۹۶، ساعت ۲۱:۲۵
        با تشکر از پاسخگویی
        من بعد از کامنت شما ، موارد مطرح شده رو پیگیری کردم و توابع مورد نیاز برای initDB و Seed رو نوشتم.
        اما چیزی که باعث شده مردد بشم دلیل حذف این موارد در نسخ جدید EF هست .
        متاسفانه طی سرچ هایی که داشتم موفق نشدم دلیل حذف این موارد رو بفهمم.آیا به خاطر سربار روی سیستم بوده ؟ یا دلیل دیگه ای داره ؟
        ممنون می‌شم اگر اطلاعی دارید بفرمایید
        همچنین سوال دیگه اینکه برخی کامندها در کنسول Package Manager موجود نیستن . مثل update-database -script . آیا راهی برای فعال سازی این موارد وجود داره ؟
        تشکر فراوان
        • #
          ‫۶ سال و ۱۱ ماه قبل، سه‌شنبه ۲۵ مهر ۱۳۹۶، ساعت ۲۱:۴۷
          - متد Seed به نگارش بعدی EF Core اضافه خواهد شد (نگارش 2.1). یک نمونه پیاده سازی آن در نگارش فعلی.
          - روش کار چندسکویی با NET Core. مبتنی بر CLI آن هست. بهتر است سری کار با VSCode را پیگیری کنید تا بیشتر با CLI آن آشنا شوید. اما اگر می‌خواهید از PowerShell استفاده کنید (هنوز حال و هوای EF 6.x را دارید)، پیشنیازهای فعالسازی این مورد در نظرات قسمت بعدی مطرح شده‌است.
          • #
            ‫۶ سال و ۶ ماه قبل، سه‌شنبه ۱۵ اسفند ۱۳۹۶، ساعت ۰۸:۴۹
            در مورد MIgration امکان این هست که بیشتر توضیح بفرماید .
            من پروژه شما رو دانلود کردم و یک کلاس ساده در بخش ApplicationDbContext  اضافه کردم جهت تست.
            اما بعد از اجرای پروژه چنین کلاسی در دیتابیس ایجاد نگردید.
            با ردیابی کلیات کار این قطعه کد رو در یک پروژه جدید ( با داشتن بخش Identity core) تست کردم که نتایج همانند قبل بود و تنها جداول Identity ایجاد گردید.
            try
                        {
                            using (var scope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
                            {
                                var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
                                db.Database.Migrate();
                               
                            }
                        }
                        catch (Exception ex)
                        {
                           //log error 
                        }

            آیا برای ردیابی تغییرات مدل و اعمال به دیتابیس به صورت اتوماتیک نیاز به کار خاص یا موردی هست که جامونده باشه ؟
            • #
              ‫۶ سال و ۶ ماه قبل، سه‌شنبه ۱۵ اسفند ۱۳۹۶، ساعت ۱۱:۱۸
              بعد از انجام تغییرات در مدل‌ها و نگاشت‌های آن‌ها، نیاز است فایل _01-add_migrations.cmd را اجرا کنید تا نحوه‌ی اعمال این تغییرات به بانک اطلاعاتی تولید شود. سپس یا فایل _02-update_db.cmd را اجرا کنید تا این تغییرات به بانک اطلاعاتی اعمال شوند، یا قطعه کد Database.Migrate هم دقیقا کار همین اسکریپت دوم را انجام می‌دهد.
              • #
                ‫۶ سال و ۶ ماه قبل، سه‌شنبه ۱۵ اسفند ۱۳۹۶، ساعت ۱۲:۲۵
                من همین کد رو از پروژه شما برداشتم و در متد Configure در فایل Startup قراردادم. و بدون خطا اجرا شد. اما جداول مورد نظر در دیتابیس ساخته نمی‌شن.
                و هنگام استفاده از موجودیت‌های جدیدی که در ApplicationDbContext  تعریف شده پیام خطای Invalid Object Name'' دریافت می‌کنم
                اما اگر به صورت دستی دستورات به روز رسانی دیتابیس رو استفاده کنم جداول مورد نظر ساخته می‌شن.
                • #
                  ‫۶ سال و ۶ ماه قبل، سه‌شنبه ۱۵ اسفند ۱۳۹۶، ساعت ۱۲:۴۰
                  چیزی به نام Automatic Migrations در EF Core وجود خارجی ندارد و حذف شده‌است و اجرای فایل _01-add_migrations.cmd برای تولید اسکریپت‌های SQL تشکیل جداول و روابط بین آن‌ها، اجباری است. کار قطعه کد Database.Migrate صرفا اجرای این اسکریپت‌های SQL اعمال نشده‌ی به بانک اطلاعاتی است و نه تولید آن‌ها.
                  • #
                    ‫۶ سال و ۶ ماه قبل، سه‌شنبه ۱۵ اسفند ۱۳۹۶، ساعت ۱۳:۳۷
                    آیا شما توصیه می‌کنید که دنبال ماژولی، توسعه ای یا راهی برای اتوماتیک کردن این مورد برم ؟ یا آیا دلیل خاصی برای حذف چنین چیزی از EF Core هست؟
                    تشکر از راهنمایی
                    • #
                      ‫۶ سال و ۶ ماه قبل، سه‌شنبه ۱۵ اسفند ۱۳۹۶، ساعت ۱۴:۲۲
                      خلاصه‌ی دلایل حذف آن‌را از زبان یکی از اعضای تیم EF در قسمت «مهاجرت خودکار از EF Core حذف شده‌است» مطلب جاری توضیح دادم.
  • #
    ‫۶ سال و ۹ ماه قبل، شنبه ۴ آذر ۱۳۹۶، ساعت ۱۸:۲۴
    من در یک پروژه دستور ایجاد migration را وارد میکنم ولی متاسفانه با خطای Build Failed روبرو میشود . در صورتی که خود پروژه به راحتی بیلد میشود. پروژه اصلی شامل پوشه بندی برای لایه دیتا و سرویس و .. میباشد و رفرنسی به پروژه دیگر برای این موضوع به آن وجود ندارد.
    • #
      ‫۶ سال و ۹ ماه قبل، شنبه ۴ آذر ۱۳۹۶، ساعت ۱۸:۴۳
      - یکبار دستور dotnet build را در ریشه‌ی پروژه‌ی اصلی و یکبار این دستور را در ریشه‌ی پروژه‌ی لایه دیتا به صورت مجزا اجرا کنید.
      - از NET Core CLI. استفاده می‌کنید (از روش ... dotnet ef)؟ از پارامتر v- آن استفاده کنید (verbose-)
      - سازنده‌ی کلاس Context شما وابستگی خاصی دارد؟ آیا IDesignTimeDbContextFactory را برای آن مشخص کرده‌اید؟
      • #
        ‫۶ سال و ۹ ماه قبل، شنبه ۴ آذر ۱۳۹۶، ساعت ۱۹:۴۲
        ممنون با بیلد کردن پروژه از طریق Cli خطایی برخوردم که شرح آن در اینجا هست.
        احتمالا در حین ارتقا از Dotnet Core 1 به 2 این مشکل پیش آمده است.
        الان فایل Migration با موفقیت ایجاد شد. سپاس
  • #
    ‫۶ سال و ۸ ماه قبل، سه‌شنبه ۲۶ دی ۱۳۹۶، ساعت ۱۳:۰۲
    بنابر این مطلب، در صورتی که بخواهیم جدول  __EFMigrationsHistory  تشکیل شده در دیتابیس، از schema متفاوتی استفاده کند، از دستور زیر استفاده می‌کنیم:
    protected override void OnConfiguring(DbContextOptionsBuilder options)
        => options.UseSqlServer(
            connectionString,
            x => x.MigrationsHistoryTable("__MyMigrationsHistory", "mySchema"));

  • #
    ‫۶ سال و ۴ ماه قبل، شنبه ۲۹ اردیبهشت ۱۳۹۷، ساعت ۱۳:۱۷
    با سلام؛ باتوجه به توضیحات مقاله فوق درباره  اینکه برای هر تغییرات با اجرای این دستورات، فایل جدید 13950526073248_v2 به پوشه‌ی Migrations اضافه می‌شود. به ازای هر تغییرات یک کلاس ایجاد میکند که ممکن برای مدت زمانی حجم کلاس‌ها زیاد شود که یا باید دستی حذف کنیم یا قبلش حذف کنیم و در مواردی هم ممکن است برای حذف کردن فراموش شوند. ممنون میشم راهنمایی بفرمایید راهکاری جز این هست یا نه؟ با تشکر  
    • #
      ‫۶ سال و ۴ ماه قبل، شنبه ۲۹ اردیبهشت ۱۳۹۷، ساعت ۱۳:۴۴
      هیچ چیزی نباید از اینجا حذف شود. این سابقه‌ی به روز رسانی‌های برنامه و بانک اطلاعاتی آن است.
  • #
    ‫۶ سال و ۳ ماه قبل، چهارشنبه ۲۳ خرداد ۱۳۹۷، ساعت ۱۳:۵۶
    ارتقاء به EF Core 2.1: مقدار دهی اولیه‌ی جداول بانک‌های اطلاعاتی
    روشی که در مطلب جاری در مورد متد Seed گفته شده‌است، هنوز هم کار می‌کند. در نگارش 2.1 روش توکاری را برای این منظور در متد OnModelCreating معرفی کرده‌اند:
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
          .HasData(new Blog { BlogId = 1, Url = "http://sample.com" });
    }
    اعمال آن نیز تنها یکبار از طریق اجرای عملیات Migrations صورت می‌گیرد و محاسبات ثبت یا به روز رسانی آن نیز خودکار است.
    اگر موجودیت در حال ثبت نیاز به تعریف کلید خارجی داشته باشد، باید از یک anonymous class استفاده کرد:
    modelBuilder.Entity<Post>().HasData(
        new {BlogId = 1, PostId = 1, Title = "First post", Content = "Test 1"},
        new {BlogId = 1, PostId = 2, Title = "Second post", Content = "Test 2"});
  • #
    ‫۵ سال و ۳ ماه قبل، دوشنبه ۲۰ خرداد ۱۳۹۸، ساعت ۱۵:۴۷
    ارتقاء به EF Core 3.0
    چون EF Core 3.0 دیگر جزئی از NET Core SDK. نیست و روند توسعه‌ی آن شتاب بیشتری خواهد گرفت، ابزارهای مرتبط با آن نیز دیگر به همراه SDK ارائه نمی‌شوند. برای مثال SDK دیگر به همراه ابزار dotnet ef نخواهد بود و باید آن‌را به صورت جداگانه‌ای دریافت و یا به روز رسانی کنید:
    dotnet tool install --global dotnet-ef --version <exact-version>
    • #
      ‫۵ سال و ۱ ماه قبل، شنبه ۱۹ مرداد ۱۳۹۸، ساعت ۱۷:۰۴
      یک نکته‌ی تکمیلی
      ممکن است در حین اجرای عملیات تولید کلاس‌های Migrations در NET Core 3.0. به خطای «ارجاعی به اسمبلی Microsoft.EntityFrameworkCore.Design در پروژه‌ی آغازین برنامه وجود ندارد» بخورید. برای رفع آن نیازی نیست تا این ارجاع را به پروژه‌ی اصلی اضافه کنید. فقط سطر قبلی زیر را
      <PackageReference Include="Microsoft.EntityFrameworkCore.Design" 
                        Version="3.0.0-preview7.19362.6"
                        PrivateAssets="all" />
      در فایل csproj مربوط به پروژه‌ی مجزای DataLayer که Context برنامه در آن قرار دارد یافته و خاصیت PrivateAssets آن‌را حذف کنید.
    • #
      ‫۵ سال قبل، دوشنبه ۱۱ شهریور ۱۳۹۸، ساعت ۰۲:۰۶
      یک نکته‌ی تکمیلی
      برای نصب آخرین نگارش 3، می‌توان از * بجای ذکر نگارش دقیق استفاده کرد:
      dotnet tool install --global dotnet-ef --version 3.0.0-*
      و همچنین برای به روز رسانی به آخرین نگارش 3:
      dotnet tool update --global dotnet-ef --version 3.0.0-*
  • #
    ‫۳ سال و ۶ ماه قبل، دوشنبه ۱۱ اسفند ۱۳۹۹، ساعت ۱۸:۴۴
    نکته تکمیلی
    اگر فایل Context شما در لایه DataLayer قرار دارد و از برنامه نویسی چند لایه استفاده میکنید و تنظیمات رشته اتصال رو بخواید از فایل Startup لایه Web به DataLayer انتقال بدید، هنگام افزودن Migrations و Update database به خطای زیر میخورید:
    Unable to create an object of type 'ApplicationDbContext'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
     که برای رفع آن باید از دستور زیر استفاده کنید:
    dotnet ef migrations add InitDb -s ../ProjectName.Web
    منظور از پرچم s اشاره به فایل Startup است، 'دو نقطه اسلش' هم برای یک مرحله برگشت از DataLayer به کنار تمام لایه‌ها و بعد وارد شدن به لایه Web پروژه مان است، ProjectName نیز نام اسمبلی است که فایل Startup در آن قرار دارد و تنظیمات رشته اتصال را به DataLayer انتقال میدهیم.
    public void ConfigureServices(IServiceCollection services)
    {
        var connectionString = Configuration["ConnectionStrings:ApplicationDbContextConnection"];
        services.AddDbContext<ApplicationDbContext>(options =>
        {
            options.UseSqlServer(connectionString);
        });
        // ...
    }
    هنگام استفاده از دستور update database هم باید مثل migrations از پرچم فوق استفاده شود.
  • #
    ‫۲ سال و ۳ ماه قبل، یکشنبه ۱۸ اردیبهشت ۱۴۰۱، ساعت ۱۴:۴۴
    جهت استفاده از ابزار dotnet ef به صورت گرافیکی در رایدار Rider  میتوانید پلاگین یا افزونه Entity Framework Core UI  را نصب نمایید