Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

Asp.NET Core 2 MVC’de Migrations İle Veritabanı İşlemleri

Merhaba,

Bu içeriğimizde Asp.NET Core 2 MVC’de migration yapısının nasıl kullanıldığını inceleyeceğiz. İlk olarak migration altyapısının kurulumunu gerçekleştirecek, ardından migration oluşturacak, süreçte migrationlar üzerinde düzenleme işlemleri gerçekleştirecek ve tüm bu işlemlerin neticesinde migration yapılarının tetiklenmesi için komut satırından veya özel olarak tasarlayacağımız bir middleware üzerinden olmak üzere iki farklı yoldan nasıl çalışılacağını inceleyeceğiz.

Şimdi gelin hiç vakit kaybetmeden altyapımızı oluşturmayla başlayalım.

Migration Altyapısının Oluşturulması

Herşeyden önce migration tarafından otomatik generate edilmesi için bir tablo temsil edecek olan entitymizi ve DbContext sınıfımızı inşa ederek işe başlayalım.

    public class Employee
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string SurName { get; set; }
        public int Age { get; set; }
    }
    public class DatabaseContext : DbContext
    {
        public DatabaseContext(DbContextOptions options)
            : base(options)
        { }
        public DbSet<Employee> Employees { get; set; }
    }

Oluşturduğumuz “DatabaseContext” sınıfı bizim “DbContext” sınıfımız olacaktır. Dolayısıyla bu sınıf tipinden olabilecek tüm taleplere karşılık bir nesne döndürebilmek için “Startup” sınıfının “ConfigureServices” metodunda aşağıdaki çalışmayı gerçekleştiriyoruz.

.
.
.
        public void ConfigureServices(IServiceCollection services)
        {
            #region DbContext
            services.AddDbContext<DatabaseContext>(option => option.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
            #endregion
            services.AddMvc();
        }
.
.
.

Burada dikkat ederseniz eğer generic olan “AddDbContext” metodu sayesinde “DatabaseContext” sınıfının bir “DbContext” olduğunu belirtmiş bulunmaktayız ve veritabanı işlemlerinde tüm taleplere karşılık ilgili sınıftan bir instance gönderilmesine dair bildiride bulunmaktayız. Ayrıca gönderilecek bu instance’da “UseSqlServer” fonksiyonu aracılığıyla Sql Server kullanılacağı belirtilmekte ve server bağlantısı “Configuration.GetConnectionString” komutu ile de “appsettings.json” dosyasında “DefaultConnection” isminde kayıtta tutulan provider ile sağlanması söylenmektedir.

“appsettings.json” dosyası; klasik Asp.NET mimarisindeki “web.config” dosyasına denk olan, Asp.NET Core ile dünyamıza giren bir dosyadır. Proje içerisinde varsayılan olarak gelmeyen “appsettings.json” dosyasını “App Settings File” isminde aratarak ismini değiştirmeksizin direkt olarak eklemeniz ilgili dosyayı projeye entegre etmeniz için yeterli olacaktır. “appsettings.json” dosyasının içeriğide aşağıdaki gibi olacaktır;

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=.;Database=ExampleDb;Trusted_Connection=True;Integrated Security=True;"
  }
}

Görüldüğü gibi, “ConnectionStrings” özelliği altında tanımlanan “DefaultConnection” özelliği, o anda bağlantı kuracağımız database bilgisinin providerını tutmaktadır.

Bu noktaya kadar yaptığımız tüm çalışma migration altyapısı için gerekli olan çoğu hususu barındırmaktadır. Şimdi migration yapılarını projeye entegre edebilmek için “Microsoft.EntityFrameworkCore.Tools.DotNet” kütüphanesini projemize eklememiz gerekmektedir. Bu işlem için projeye sağ tıklayıp “Edit -ProjeAdi-.csproj” sekmesine tıklayınız ve aşağıda olduğu gibi ilgili paketi ekleyiniz.

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <Folder Include="Views\Shared\" />
    <Folder Include="wwwroot\" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.1" />
    <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.3" />
  </ItemGroup>

</Project>

Eğer ki, projeye entegre etmeye çalıştığımız paketin son versiyon bilgisini bilmiyorsanız şu adresten bakıp teyit edebilirsiniz.

Migration Oluşturma/Ekleme

Tüm bu işlemleri yaptıktan sonra artık projemizde migrations yapılarını oluşturabiliriz. Bu işlem için projenin dizininde komut satırını açarak aşağıdaki prototipte olan komutu yazmanız yeterlidir.

dotnet ef migrations add [migration adı]

Asp.NET Core 2 MVC'de Migrations İle Veritabanı İşlemleri
Bu işlemi yaptıktan sonra projemize Solution Explorer penceresinden bakarsak eğer “Migrations” isminde bir klasörün eklendiğini görmekteyiz.
Asp.NET Core 2 MVC'de Migrations İle Veritabanı İşlemleri
İlgili klasör içerisinde ilk etapta biri migration bir diğeri ise “Startup” sınıfında DbContext olarak belirttiğimiz sınıfın Snapshot sınıfları gelmektedir. Bu sınıflar içerisine sırasıyla göz atarsak eğer;

İlk olarak migration sınıfımızı inceleyeceğiz;

    public partial class initial : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.CreateTable(
                name: "Employees",
                columns: table => new
                {
                    Id = table.Column<int>(nullable: false)
                        .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
                    Name = table.Column<string>(nullable: true),
                    SurName = table.Column<string>(nullable: true),
                    Age = table.Column<int>(nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Employees", x => x.Id);
                });
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropTable(
                name: "Employees");
        }
    }

Oluşturulan migration sınıfında sistem “Startup” sınıfı içerisinde tanımlanmış “DbContext” sınıfı içerisinde “DbSet<T>” tipinde tablo olarak tanımlanmış tüm sınıfları yakalamakta ve “Up” metodu içerisinde generate etmektedir. Burada dikkat edilmesi gereken nokta “Up” metodu değişiklikleri uygulamak için kullanılırken, “Down” metodu ise yapılan tüm değişiklikleri geri almak için kullanılmaktadır.

Snapshot sınıfına göz atarsak eğer;

    [DbContext(typeof(DatabaseContext))]
    partial class DatabaseContextModelSnapshot : ModelSnapshot
    {
        protected override void BuildModel(ModelBuilder modelBuilder)
        {
#pragma warning disable 612, 618
            modelBuilder
                .HasAnnotation("ProductVersion", "2.1.3-rtm-32065")
                .HasAnnotation("Relational:MaxIdentifierLength", 128)
                .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);

            modelBuilder.Entity("CoreMigrations.Models.Entities.Employee", b =>
                {
                    b.Property<int>("Id")
                        .ValueGeneratedOnAdd()
                        .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);

                    b.Property<int>("Age");

                    b.Property<string>("Name");

                    b.Property<string>("SurName");

                    b.HasKey("Id");

                    b.ToTable("Employees");
                });
#pragma warning restore 612, 618
        }
    }

burada model ile ilgili tüm yapılar inşa edilmektedir.

Migrationları Migrate Ederek Veritabanına Yansıtmak

Evet… Tüm altyapımızı kurduk. Migrationlarımızı oluşturduk. Şimdi oluşturulan migrationları migrate ederek veritabanına yansıtalım. Bu işlem için biri komut satırından bir diğeride programatik olmak üzere iki farklı yol mevcuttur. Bizler her iki yoluda inceleyeceğiz;

İlk olarak komut satırında migrate işlemini görelim.

Projemizdeki migrationları migrate edebilmek için komut satırından aşağıdaki prototipte bulunan komutu çalıştırmamız yeterlidir.

dotnet ef database update

Asp.NET Core 2 MVC'de Migrations İle Veritabanı İşlemleri
Bu işlemden sonra SQL Server’a göz atarsak eğer aşağıdaki ekran görüntüsünde olduğu gibi veritabanımızın oluşturulduğunu ve içerisine ilgili tablonun eklendiğini göreceğiz.
Asp.NET Core 2 MVC'de Migrations İle Veritabanı İşlemleri
Hatta dikkat ederseniz eğer ilgili tablonun “Id” kolonuna otomatik bir şekilde primary key constrainti eklenmekte ve belirtilen tüm ayarlar kolonlara yansıtılmaktadır.

Migrate işleminin programatik olarak gerçekleştirilmesini istiyorsanız eğer “Startup” sınıfı içerisindeki “Configure” isimli metotta aşağıdaki çalışmayı gerçekleştirmemiz yeterli olacaktır.

.
.
.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
                app.UseDeveloperExceptionPage();

            app.UseMvcWithDefaultRoute();
            app.UseStaticFiles();

            using (var serviceScope = app.ApplicationServices.CreateScope())
            {
                //Uygulamanın kullandığı DatabaseContext sınıfından bir örnek alıyoruz.
                DatabaseContext context = serviceScope.ServiceProvider.GetRequiredService<DatabaseContext>();
                //DbContext'i migrate ediyoruz.
                context.Database.Migrate();
            }
        }
.
.
.

Kodumuzu bu şekilde inşa ettikten sonra projeyi derleyip çalıştırmanız ilgili migrationların migrate olması için yeterli olacak ve veritabanı, tablolar vs. yapıları oluşturulup proje o şekilde ayağa kaldırılacaktır.

Entity Güncelleme Durumları

Migration’ın oluşturduğu entity üzerinde bir değişiklik meydana geldiği zaman ilgili değişikliği yakalayacak yeni bir migration eklemek en doğrusu olacaktır. Örneğin; “Employee” sınıfına “Date” propertysi ekleyerek değişiklik yaptığımızı düşünelim.

    public class Employee
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string SurName { get; set; }
        public int Age { get; set; }

        public DateTime Date { get; set; }
    }

Şimdi bu değişikliği yakalaması için yeni bir migration oluşturalım.
Asp.NET Core 2 MVC'de Migrations İle Veritabanı İşlemleri

Asp.NET Core 2 MVC'de Migrations İle Veritabanı İşlemleri
Yukarıdaki ekran görüntüsüne dikkat ederseniz oluşturduğumuz migration ilgili klasöre eklenmiştir. İçeriğine göz atarsak eğer;

    public partial class EmployeeAddDateProp : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.AddColumn<DateTime>(
                name: "Date",
                table: "Employees",
                nullable: false,
                defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropColumn(
                name: "Date",
                table: "Employees");
        }
    }

gördüğünüz üzere bu sefer “Employee” entitysindeki değişiklik yakalanmıştır ve bir kolon ekleme işlemi yapılmaktadır.

Şimdi tek yapmamız gereken bu migrationı ya komut satırından ya da programatik olarak migrate etmemiz gerekmektedir. Bu işlem için önceki satırlarda ele aldığımız her iki yöntemden birini uygularsanız veritabanına ilgili değişikliğin yansıtıldığını göreceksiniz.

Migrationları Geri Almak ya da Belirli Bir Migrationa Geri Dönmek

Migrationları geri almak istiyorsanız tek yapmanız gereken geri dönmek istediğiniz migration adını update komutunun sonuna aşağıdaki gibi belirtmeniz gerekmektedir.

dotnet ef database update [migration adı]

Bu kalıpta komutu çalıştırdığınızda aradaki tüm migration işlemleri geri alınacak ve veritabanı belirtilen migrationın ayarlarına göre tasarlanacaktır.

İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…

İyi çalışmalar…

Bunlar da hoşunuza gidebilir...

13 Cevaplar

  1. cabbar dedi ki:

    ne dotnet miş yaw, bir migrations eklemek bu kadar uzun ve zor olurmu? php nin gözünü seveyim. Kaç gündür şu veri tabanı işlemlerini çözemedim, bir şeyi yapmak için 50 tane işlem yapmak zorunda kalıyoruz. Emeğinize sağlık. Hocam bunun daha basit bir yöntemi yok mu? otomatik oluşturamıyormuyuz bunu?

  2. Saniye Apaydın dedi ki:

    Gerçekten çok faydalı bir yazı olmuş çok faydalanma fırsatı buldum. Çok teşekkür ederim.

  3. Ayşe Yücel dedi ki:

    Çok sağolun sizi takip ederek geçtim aşamaları. yoksa tıkanıp kalmıştım. basit anlatım ile iyi öğrenme.

    Teşekkürler.

  4. Abdullatif dedi ki:

    Çok faydalı bir yazı ancak telefon boyutunda kodlar tam gözükmüyor
    Bir de ben migratinos oluşturuyorum up ve down metodları boş geliyor sebebi nedir ?
    Sorumu cevaplarsanı çok sevinirim
    Güzel yazı
    Teşekkürler

    • Gençay dedi ki:

      Merhaba,

      Migration context nesnesinde yapılan değişiklikleri yakalayarak oluşturulur. Eğer ki ilgili fonksiyonlar boş geliyorsa, tüm değişiklikleri karşılayan önceden oluşturulmuş bir migration’ın mevcut olup olmadığını kontrol edebilir misiniz?

      Kolay gelsin.
      Teşekkürler.

  5. Ramazan dedi ki:

    Merhabalar, çok faydalı bir yazı olmuş. Takıldığım bir nokta var. add-migration yaptıktan sonra ve sonrasında update-database yaptıktan sonra migration ve database oluşturuluyor orası normal. Fakat sonradan database e bir tablo daha eklemek istediğimde update-database komutu ile database ve migration yenilenmiyor. Başka bir yöntemi mi var ?

    • Gençay dedi ki:

      Merhaba,

      Yapılan değişiklikler en son add-migration [name] komutu ile basılan migration tarafından tekrar yakalanıp, ardından update-database yapılmalıdır.

      Kolay gelsin.

      • Ramazan dedi ki:

        yani tabloda her yaptığımız değişiklik için add-migration ile yeni bir migration oluşturup update-database mi yapmamız gerekiyor ?

  6. Ali GÖKDENİZ dedi ki:

    up and down() method Migration da Neden Boş Oluşturuyor ?

  7. ömer faruk dedi ki:

    merhaba ,
    Güzel bir içerik olmuş, yalnız size bir sorum olacak. Migration uyguluyorum fakat metotların içerisi boş kalıyor ve veri tabanında da kurmak istediğim ilişkiler oluşturulmuyor. Yardımcı olur musunuz ?

    using Microsoft.EntityFrameworkCore.Migrations;
    
    namespace DataAccessLayer.Migrations
    {
        public partial class mig_writer_blog_relationn : Migration
        {
            protected override void Up(MigrationBuilder migrationBuilder)
            {
    
            }
    
            protected override void Down(MigrationBuilder migrationBuilder)
            {
            }
        }
    }
    

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir