مروری بر Migration در روش Code First با Entity Framework

سه شنبه 28 مهر 1394

همیشه توسعه دهندگان وب در طول توسعه برنامه های خود با چالش های بسیاری روبرو هستند. ممکن است در حین انجام کار لازم باشد کلاس ها موجود در مدل را تغییر دهند و یا کلاس جدیدی به مدل اضافه کنند که باعث عدم تطابق بین کلاسهای موجود و کلاس های اضافه شده می شود. در این مقاله مقدار دهی اولیه پایگاه داده و ویژگی های متنوع migration در Entity Framework code first را ارائه می دهیم.

مروری بر Migration در روش Code First با Entity Framework

مقدمه:

روش  Entity Framework code first به شما اجازه می دهد که کلاس های POCO(کلاس هایی که به عنوان مدل ایجاد می کنیم) را ایجاد کنید و پایگاه داده مورد نظر را بسازید و یا پایگاه داده موجود را تغییر دهید. Entity Framework کنترل کاملی بر تولید جدول داده و اصلاح پایگاه داده در حال استفاده و Migration دارد.

توضیح روش:

Migration یک مفهوم بسیار مفید برای مدیریت انواع تغییرات در پایگاه داده می باشد. با استفاده از Migration می توانید به راحتی پایگاه داده جدید بسازید و یا پایگاه داده موجود را به روز رسانی و حتی حذف کنید.

لطفا قبل از شروع حتما دو مقاله زیر را مطالعه فرمایید:

شروع کار با روش Code First در Entity Framework

روش Entity Framework Code First در Asp.net MVC

مقدار دهی اولیه پایگاه داده (Database Initializers)

رویکرد Entity Framework code first، پایگاه داده را به طور اتوماتیک و بر اساس کلاس های POCO ایجاد می کند. به طور پیش فرض Database Initializer (مقدار دهی اولیه پایگاه داده) این اعمال را مدیریت می کند.

Entity Framework چهار مقدار دهی اولیه پایه دارد که به صورت زیر تعریف می شوند:

1. CreateDatabaseIfNotExists: اگر پایگاه داده وجود نداشته باشدآن را ایجاد می کند.

2. DropCreateDatabaseWhenModelChanges: هنگامی که مدل تغییر کند، تغییرات را در پایگاه داده اعمال می کند.

3.DropCreateDatabaseAlways: پایگاه داده را به آخرین وژن موجود منتقل می کند.

MigrateDatabaseToLatestVersion .4: به تازگی به ورژن EF 6.0 اضافه شده است که پایگاه داده را به آخرین ورژن موجود به روز رسانی می کند.

 

CreateDatabaseIfNotExists

کلاس مقدار دهی پیش فرض پایگاه داده است، مگر اینکه شما کلاس دیگری را از قبل اعلام کرده باشید. همانطور که از نام کلاس مشخص است، اگر پایگاه داده موجود نباشد، یک پایگاه داده جدید می سازد.

DropCreateDatabaseWhenModelChanges

این کلاس Database Initializer تمام پایگاه داده را هر زمان که هر گونه تغییر در داده های Model ایجاد شود دوباره ایجاد می کند. این کلاس در طول مراحل برنامه نویسی زمانیکه هیچ نگرانی در مورد رکوردهای پایگاه داده موجود ندارید، مفید است.

DropCreateDatabaseAlways

این کلاس همیشه پایگاه داده موجود را حذف کرده و پایگاه داده جدید را در هر زمان که برنامه اجرا می شود دوباره ایجاد می کند. این Initializer زمانیکه شما می خواهید پایگاه داده را هر بار تازه کنید(Refresh) مناسب است.

MigrateDatabaseToLatestVersion

این مقدار دهی اولیه پایگاه داده، در Entity Framework نسخه 6 اضافه شده است. این initializer برای به روز رسانی پایگاه داده به آخرین ورژن استفاده می شود. این مورد برای به روز رسانی پایگاه داده بدون حذف رکوردهای پایگاه داده بسیار مناسب است.

اگر می خواهید در کلاس های Database initializer بیشتر نفوذ داشته باشید، می توانید کلاس custom database initializer را به طور دستی فعال کنید.

کجا باید Database Initializers را اعلام کرد؟

روش پایه برای اعلام Database Initializers در کلاس سازنده DbContext است.

StudentDbContext.cs

public class StudentDbContext : DbContext
{
    public StudentDbContext ()
         : base("StudentDbContext")
    {
       Database.SetInitializer(new DropCreateDatabaseWhenModelChanges());
    }
    public DbSet<Student> Students { get; set; }
    public DbSet<Department> Departments { get; set; }
}

 

Migration نقش مهمی در تغییرات پایگاه داده و رکوردهای موجود در پایگاه داده دارد که هر دو برای ما مهم است.

Migration می تواند رکوردهای حاضر در پایگاه داده موجود را تغییر دهد، و یا هرکدام از رکوردها را حذف کند.

دو نوع migration وجود دارد:

1.اتوماتیک

2. Code base یا دستی

در این مقاله ما Migration نوع Code base یا دستی را مورد بررسی قرار می دهیم.

فعال کردن Migration

برای فعال سازی Migration در برنامه خود به تب Tool رفته و بعد از انتخاب Nuget Package Manager در نهایت Package Manager Console را انتخاب کنید.

توجه: پروژه را در جایی که فایل DataContext وجود دارد انتخاب کنید.

دستور زیر را در کنسول بنویسید:

PM>Enable-Migrations

زمانی که دستور Enable-Migrations را فعال می کنیم به طور اتوماتیک، کلاس DataContext کنترل می کند که به پایگاه داده موجود مربوط است یا خیر. این دستور پوشه " Migrations" را در پروژه ایجاد می کند.

توجه: شما می توانید به صورت خودکار migration را از طریق دستور Enable-Migrations –EnableAutomaticMigrations تنظیم کنید.

Configuration class

شما می توانید تنظیمات سطح پیکربندی را در سازنده اضافه کنید، بنابراین به طور خودکار زمانی که نمونه شی کلاس پیکر بندی، تولید شود، مقداردهی اولیه می شود.

AutomaticMigrationsEnabled= falseپراپرتی از migration در هر بار اجرای برنامه از Migration اتوماتیک جلوگیری می کند. شما می توانید ویژگی دیگر AutomaticMigrationDataLossAllowed = false را اضافه کنید. این برای جلوگیری از دست دادن داده ها می باشد. متد Seed برای وارد کردن مقادیر پیش فرض در جدول داده ها استفاده می شود. کلاس فوق به صورت زیر است:


namespace MVCEFCodeFirstApp.Migrations
{
    using System;
    using System.Data.Entity;
    using System.Data.Entity.Migrations;
    using System.Linq;

    internal sealed class Configuration : DbMigrationsConfiguration<MVCEFCodeFirstApp.Models.StudentDbContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
            ContextKey = "MVCEFCodeFirstApp.Models.StudentDbContext";
        }

        protected override void Seed(MVCEFCodeFirstApp.Models.StudentDbContext context)
        {
            //  This method will be called after migrating to the latest version.

            //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
            //  to avoid creating duplicate seed data. E.g.
            //
            //    context.People.AddOrUpdate(
            //      p => p.FullName,
            //      new Person { FullName = "Andrew Peters" },
            //      new Person { FullName = "Brice Lambson" },
            //      new Person { FullName = "Rowan Miller" }
            //    );
            //
        }
    }
}

کلاس migration برای InitialCreate

هر کلاس migration دو متد ()Up و ()Down دارد. شما می توانید متدهای Up و Down را برای هر تغییر به روز رسانی کنید. هنگامی که migration رااجرا می کنیم، روش Up بوسیله فراخوانی پیش فرض و به روز رسانی پایگاه داده بر اساس کد نوشته شده در حوزه خود است.

متد Down دقیقا مخالف متد Up است. متد Down زمانی که می خواهیم migration را برگردانیم استفاده خواهد شد. در مثال ما متد Up جدول های Department و Student را ایجا می کند که آیا در متد Down، تمام جدوا های انداختن و حذف کردن تمام محدودیت ها است و به صورت زیر است:

namespace MVCEFCodeFirstApp.Migrations
{
    using System;
    using System.Data.Entity.Migrations;
    
    public partial class InitialCreate : DbMigration
    {
        public override void Up()
        {
            CreateTable(
                "dbo.Departments",
                c => new
                    {
                        DepartmentId = c.Int(nullable: false, identity: true),
                        DepartmentName = c.String(),
                    })
                .PrimaryKey(t => t.DepartmentId);
            
            CreateTable(
                "dbo.Students",
                c => new
                    {
                        StudentId = c.Int(nullable: false, identity: true),
                        Name = c.String(),
                        DateOfBirth = c.DateTime(),
                        EmailId = c.String(),
                        Address = c.String(),
                        City = c.String(),
                        Department_DepartmentId = c.Int(),
                    })
                .PrimaryKey(t => t.StudentId)
                .ForeignKey("dbo.Departments", t => t.Department_DepartmentId)
                .Index(t => t.Department_DepartmentId);
            
        }
        
        public override void Down()
        {
            DropForeignKey("dbo.Students", "Department_DepartmentId", "dbo.Departments");
            DropIndex("dbo.Students", new[] { "Department_DepartmentId" });
            DropTable("dbo.Students");
            DropTable("dbo.Departments");
        }
    }
}

 

فعال سازی Migration به طور خودکار جدول جدید MigrationsHistory را در پایگاه داده اضافه می کند. MigrationId منحصر به فرد بوده و دقیقا شبیه نام migration شما در برنامه می باشد. ContextKey مدل Context مناسب را نشان می دهد.

اضافه کردن migration

در حال حاضر فیلد Country را در کلاس  Student.cs اضافه کنید و migration جدید در پروژه اضافه کنید

دستور زیر را در کنسول Package Manager برای اضافه کردن Package Manager بنویسید. این یک کلاس migration جدید در پوشه Migration شما اضافه می کند. کلاس مورد نظر به صورت زیر است:

    public class Student
    { 
      public Student()
    {

    }
    [Key]
    public int StudentId { get; set; }
    public string Name { get; set; }

    [DataType(DataType.Date), 
     DisplayFormat(DataFormatString = "{0:dd/MM/yy}", 
     ApplyFormatInEditMode = true)]
    public DateTime? DateOfBirth { get; set; }
    public string EmailId { get; set; }
    public string Address { get; set; }
    public string City { get; set; }

    public Department Department { get; set; } // Navigation Property
    }

 

دستور زیر را در Package Manager Console برای اضافه کردن migration بنویسید:

PM> Add migrations AddCountryToStudent

این یک Migration جدید به پوشه Migrations اضافه می کند:

using System.Data.Entity.Migrations;
namespace MVCEFCodeFirstApp.Migrations
{
    public partial class AddCountryToStudent : DbMigration
    {
        public override void Up()
        {
            AddColumn("dbo.Student", "Country", c => c.String());
        }
        
        public override void Down()
        {
            DropColumn("dbo.Student", "Country");
        }
    }
}

 

به روز رسانی پایگاه داده

زمانی که ما در حال اضافه کردن migration جدید هستیم نباید فراموش کنیم که پایگاه داده برای همگام سازی باید به روز رسانی شود. برای به روز رسانی پایگاه داده کد زیر را در کنسول Package Manager بنویسید.

PM>Update-Database -Verbose

-verbose زمانی استفاده می شود که شما بخواهید توسط SQL از بانک query بگیرید. بعد از اجرای دستور update-database ، آن پایگاه داده را همگام و به روز رسانی می کند.

 

فایل های ضمیمه

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید