Aracılığıyla paylaş


Bölüm 4, Razor ASP.NET Core'da geçişleri olan EF Core sayfalar

Tom Dykstra, Jon P Smith ve Rick Anderson tarafından

Contoso University web uygulaması, ve Visual Studio kullanarak EF Core Sayfalar web uygulamalarının nasıl oluşturulacağını Razor gösterir. Öğretici serisi hakkında bilgi için ilk öğreticiye bakın.

Çözemediğiniz sorunlarla karşılaşırsanız, tamamlanmış uygulamayı indirin ve öğreticiyi izleyerek bu kodu oluşturduğunuz kodla karşılaştırın.

Bu öğreticide EF Core veri modeli değişikliklerini yönetmeye yönelik geçişler özelliği tanıtılmaktadır.

Yeni bir uygulama geliştirildiğinde veri modeli sık sık değişir. Model her değiştiğinde, model veritabanıyla eşitlenmemiş olur. Bu öğretici serisi, Entity Framework yoksa veritabanını oluşturacak şekilde yapılandırılarak başladı. Veri modeli her değiştiğinde veritabanının bırakılması gerekir. Uygulama bir sonraki çalıştırıldığında, veritabanını yeni veri modeliyle eşleşecek şekilde yeniden oluşturma çağrısı EnsureCreated yapılır. Sınıf DbInitializer daha sonra çalıştırarak yeni veritabanının tohumunu oluşturur.

Db'yi veri modeliyle eşitlenmiş durumda tutmaya yönelik bu yaklaşım, uygulamanın üretime dağıtılması gerekene kadar düzgün çalışır. Uygulama üretimde çalışırken, genellikle korunması gereken verileri depolar. Uygulama, her değişiklik yapıldığında (yeni sütun ekleme gibi) test veritabanıyla başlayamaz. EF Core Geçişler özelliği, yeni veritabanı oluşturmak yerine VERITABANı şemasını güncelleştirmeyi etkinleştirerek EF Core bu sorunu çözer.

Veri modeli değiştiğinde veritabanını bırakmak ve yeniden oluşturmak yerine geçişler şemayı güncelleştirir ve mevcut verileri korur.

Not

SQLite sınırlamaları

Bu öğreticide mümkün olduğunca Entity Framework Core geçişleri özelliği kullanılır. Geçişler veritabanı şemasını veri modelindeki değişikliklerle eşleşecek şekilde güncelleştirir. Ancak, geçişler yalnızca veritabanı altyapısının desteklediği değişiklik türlerini yapar ve SQLite'in şema değişikliği özellikleri sınırlıdır. Örneğin, sütun ekleme desteklenir, ancak sütunun kaldırılması desteklenmez. Sütunu kaldırmak için bir geçiş oluşturulursa, ef migrations add komut başarılı olur ancak ef database update komut başarısız olur.

SQLite sınırlamaları için geçici çözüm, tablodaki bir şey değiştiğinde tablo yeniden derlemesi gerçekleştirmek için geçiş kodunu el ile yazmaktır. Kod, geçiş için ve Down yöntemlerine Up gider ve şunları içerir:

  • Yeni tablo oluşturma.
  • Eski tablodan yeni tabloya veri kopyalama.
  • Eski masayı bırak.
  • Yeni tablo yeniden adlandırıyor.

Bu türdeki veritabanına özgü kod yazmak bu öğreticinin kapsamı dışındadır. Bunun yerine, geçiş uygulama girişimi başarısız olduğunda bu öğretici veritabanını bırakır ve yeniden oluşturur. Daha fazla bilgi edinmek için aşağıdaki kaynaklara bakın:

Veritabanını bırakma

Veritabanını silmek için SQL Server Nesne Gezgini (SSOX) kullanın veya Paket Yöneticisi Konsolu'nda (PMC) aşağıdaki komutu çalıştırın:

Drop-Database

İlk geçiş oluşturma

PMC'de aşağıdaki komutları çalıştırın:

Add-Migration InitialCreate
Update-Database

Kaldır EnsureCreated

Bu öğretici serisi kullanılarak EnsureCreatedbaşlatıldı. EnsureCreated bir geçiş geçmişi tablosu oluşturmaz ve bu nedenle geçişlerle kullanılamaz. Veritabanının sık sık bırakıldığı ve yeniden oluşturulduğu test veya hızlı prototip oluşturma için tasarlanmıştır.

Bu noktadan sonra öğreticiler geçişleri kullanacaktır.

içinde Program.csaşağıdaki satırı silin:

context.Database.EnsureCreated();

Uygulamayı çalıştırın ve veritabanının dağıtıldığını doğrulayın.

Yukarı ve Aşağı yöntemleri

EF Coremigrations add Komut, veritabanını oluşturmak için kod oluşturdu. Bu geçiş kodu dosyasındadır Migrations\<timestamp>_InitialCreate.cs . Up sınıfının yöntemiInitialCreate, veri modeli varlık kümelerine karşılık gelen veritabanı tablolarını oluşturur. yöntemi Down , aşağıdaki örnekte gösterildiği gibi bunları siler:

using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;

namespace ContosoUniversity.Migrations
{
    public partial class InitialCreate : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.CreateTable(
                name: "Course",
                columns: table => new
                {
                    CourseID = table.Column<int>(nullable: false),
                    Title = table.Column<string>(nullable: true),
                    Credits = table.Column<int>(nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Course", x => x.CourseID);
                });

            migrationBuilder.CreateTable(
                name: "Student",
                columns: table => new
                {
                    ID = table.Column<int>(nullable: false)
                        .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
                    LastName = table.Column<string>(nullable: true),
                    FirstMidName = table.Column<string>(nullable: true),
                    EnrollmentDate = table.Column<DateTime>(nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Student", x => x.ID);
                });

            migrationBuilder.CreateTable(
                name: "Enrollment",
                columns: table => new
                {
                    EnrollmentID = table.Column<int>(nullable: false)
                        .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
                    CourseID = table.Column<int>(nullable: false),
                    StudentID = table.Column<int>(nullable: false),
                    Grade = table.Column<int>(nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Enrollment", x => x.EnrollmentID);
                    table.ForeignKey(
                        name: "FK_Enrollment_Course_CourseID",
                        column: x => x.CourseID,
                        principalTable: "Course",
                        principalColumn: "CourseID",
                        onDelete: ReferentialAction.Cascade);
                    table.ForeignKey(
                        name: "FK_Enrollment_Student_StudentID",
                        column: x => x.StudentID,
                        principalTable: "Student",
                        principalColumn: "ID",
                        onDelete: ReferentialAction.Cascade);
                });

            migrationBuilder.CreateIndex(
                name: "IX_Enrollment_CourseID",
                table: "Enrollment",
                column: "CourseID");

            migrationBuilder.CreateIndex(
                name: "IX_Enrollment_StudentID",
                table: "Enrollment",
                column: "StudentID");
        }

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

            migrationBuilder.DropTable(
                name: "Course");

            migrationBuilder.DropTable(
                name: "Student");
        }
    }
}

Yukarıdaki kod ilk geçişe yöneliktir. Kod:

  • komutu tarafından migrations add InitialCreate oluşturuldu.
  • komutu tarafından database update yürütülür.
  • Veritabanı bağlam sınıfı tarafından belirtilen veri modeli için bir veritabanı oluşturur.

Geçiş adı parametresi (InitialCreate örnekte) dosya adı için kullanılır. Geçiş adı geçerli herhangi bir dosya adı olabilir. Geçişte yapılan işlemleri özetleyen bir sözcük veya tümcecik seçmek en iyisidir. Örneğin, bölüm tablosu ekleyen bir geçiş "AddDepartmentTable" olarak adlandırılabilir.

Geçiş geçmişi tablosu

  • Veritabanını incelemek için SSOX veya SQLite aracını kullanın.
  • Tablo eklemeye __EFMigrationsHistory dikkat edin. Tablo, __EFMigrationsHistory veritabanına hangi geçişlerin uygulandığını izler.
  • Tablodaki __EFMigrationsHistory verileri görüntüleyin. İlk geçiş için bir satır gösterir.

Veri modeli anlık görüntüsü

Geçişler, içinde Migrations/SchoolContextModelSnapshot.csgeçerli veri modelinin anlık görüntüsünü oluşturur. Geçiş eklendiğinde EF, geçerli veri modelini anlık görüntü dosyasıyla karşılaştırarak nelerin değiştiğini belirler.

Anlık görüntü dosyası veri modelinin durumunu izlediğinden, dosyayı silerek <timestamp>_<migrationname>.cs geçiş silinemez. En son geçişi geri almak için komutunu kullanın migrations remove . migrations remove geçişi siler ve anlık görüntünün doğru şekilde sıfırlanmasını sağlar. Daha fazla bilgi için bkz . dotnet ef migrations remove.

Tüm geçişleri kaldırmak için bkz . Tüm geçişleri sıfırlama.

Üretimde geçişleri uygulama

Üretim uygulamalarının uygulama başlangıcında Database.Migrate'ı çağırmamalarını öneririz. Migrate sunucu grubuna dağıtılan bir uygulamadan çağrılmamalıdır. Uygulamanın ölçeği birden çok sunucu örneğine genişletildiyse, veritabanı şeması güncelleştirmelerinin birden çok sunucudan gerçekleşmediğinden veya okuma/yazma erişimiyle çakışmadığından emin olmak zordur.

Veritabanı geçişi, dağıtımın bir parçası olarak ve denetimli bir şekilde yapılmalıdır. Üretim veritabanı geçiş yaklaşımları şunlardır:

  • SQL betikleri oluşturmak için geçişleri kullanma ve dağıtımda SQL betiklerini kullanma.
  • Denetimli bir ortamdan çalıştırma dotnet ef database update .

Sorun giderme

Uygulama SQL Server LocalDB kullanıyorsa ve aşağıdaki özel durumu görüntülüyorsa:

SqlException: Cannot open database "ContosoUniversity" requested by the login.
The login failed.
Login failed for user 'user name'.

Çözüm bir komut isteminde çalışmak dotnet ef database update olabilir.

Ek kaynaklar

Sonraki adımlar

Sonraki öğretici, varlık özellikleri ve yeni varlıklar ekleyerek veri modelini oluşturur.

Bu öğreticide EF Core , veri modeli değişikliklerini yönetmek için geçişler özelliği kullanılır.

Çözemediğiniz sorunlarla karşılaşırsanız tamamlanmış uygulamayı indirin.

Yeni bir uygulama geliştirildiğinde veri modeli sık sık değişir. Model her değiştiğinde, model veritabanıyla eşitlenmemiş olur. Bu öğretici, entity framework yoksa veritabanını oluşturacak şekilde yapılandırılarak başladı. Veri modeli her değiştiğinde:

  • Veritabanı bırakılır.
  • EF, modelle eşleşen yeni bir tane oluşturur.
  • Uygulama, test verileriyle db'yi tohumlar.

Db'yi veri modeliyle eşitlenmiş durumda tutmaya yönelik bu yaklaşım, uygulamanın üretime dağıtılması gerekene kadar düzgün çalışır. Uygulama üretimde çalışırken, genellikle korunması gereken verileri depolar. Uygulama, her değişiklik yapıldığında (yeni sütun ekleme gibi) test veritabanıyla başlayamaz. EF Core Geçişler özelliği, yeni veritabanı oluşturmak yerine VERITABANı şemasını güncelleştirmeyi etkinleştirerek EF Core bu sorunu çözer.

Veri modeli değiştiğinde veritabanını bırakıp yeniden oluşturma yerine geçişler şemayı güncelleştirir ve mevcut verileri korur.

Veritabanını bırakma

SQL Server Nesne Gezgini (SSOX) veya database drop komutunu kullanın:

Paket Yöneticisi Konsolu'nda (PMC) aşağıdaki komutu çalıştırın:

Drop-Database

Yardım bilgilerini almak için PMC'den komutunu çalıştırın Get-Help about_EntityFrameworkCore .

İlk geçiş oluşturma ve db'yi güncelleştirme

Projeyi oluşturun ve ilk geçişi oluşturun.

Add-Migration InitialCreate
Update-Database

Yukarı ve Aşağı yöntemlerini inceleme

EF Coremigrations add Komut, veritabanını oluşturmak için kod oluşturdu. Bu geçiş kodu dosyasındadır Migrations\<timestamp>_InitialCreate.cs . Up sınıfının yöntemiInitialCreate, veri modeli varlık kümelerine karşılık gelen veritabanı tablolarını oluşturur. yöntemi Down , aşağıdaki örnekte gösterildiği gibi bunları siler:

public partial class InitialCreate : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.CreateTable(
            name: "Course",
            columns: table => new
            {
                CourseID = table.Column<int>(nullable: false),
                Title = table.Column<string>(nullable: true),
                Credits = table.Column<int>(nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Course", x => x.CourseID);
            });

        migrationBuilder.CreateTable(
    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropTable(
            name: "Enrollment");

        migrationBuilder.DropTable(
            name: "Course");

        migrationBuilder.DropTable(
            name: "Student");
    }
}

Geçişler, geçiş için veri modeli değişikliklerini uygulamak için yöntemini çağırır Up . Güncelleştirmeyi geri almak için bir komut girildiğinde, geçişler yöntemini çağırır Down .

Yukarıdaki kod ilk geçişe yöneliktir. Bu kod, komut çalıştırıldığında migrations add InitialCreate oluşturulmuştur. Dosya adı için geçiş adı parametresi ("Örnekte initialCreate" kullanılır). Geçiş adı geçerli herhangi bir dosya adı olabilir. Geçişte yapılan işlemleri özetleyen bir sözcük veya tümcecik seçmek en iyisidir. Örneğin, bölüm tablosu ekleyen bir geçiş "AddDepartmentTable" olarak adlandırılabilir.

İlk geçiş oluşturulduysa ve veritabanı mevcutsa:

  • Veritabanı oluşturma kodu oluşturulur.
  • Veritabanı veri modeliyle zaten eşleştiğinden veritabanı oluşturma kodunun çalıştırılması gerekmez. Veritabanı oluşturma kodu çalıştırılırsa, veritabanı veri modeliyle zaten eşleştiğinden herhangi bir değişiklik yapmaz.

Uygulama yeni bir ortama dağıtıldığında, veritabanı oluşturma kodunun veritabanı oluşturmak için çalıştırılması gerekir.

Daha önce veritabanı bırakıldı ve mevcut değildi, bu nedenle geçişler yeni veritabanı oluşturur.

Veri modeli anlık görüntüsü

Geçişler, içinde Migrations/SchoolContextModelSnapshot.csgeçerli veritabanı şemasının anlık görüntüsünü oluşturur. Geçiş eklediğinizde EF, veri modelini anlık görüntü dosyasıyla karşılaştırarak nelerin değiştiğini belirler.

Geçişi silmek için aşağıdaki komutu kullanın:

Geçişi Kaldır

Geçişleri kaldır komutu geçişi siler ve anlık görüntünün doğru şekilde sıfırlanmasını sağlar.

EnsureCreated öğesini kaldırın ve uygulamayı test edin

Erken gelişim için EnsureCreated kullanıldı. Bu öğreticide geçişler kullanılır. EnsureCreated aşağıdaki sınırlamalara sahiptir:

  • Geçişleri atlar ve veritabanı ile şemayı oluşturur.
  • Geçiş tablosu oluşturmaz.
  • Geçişlerle kullanılamaz.
  • Db'nin sık sık bırakıldığı ve yeniden oluşturulduğu test veya hızlı prototip oluşturma için tasarlanmıştır.

öğesini kaldırın EnsureCreated:

context.Database.EnsureCreated();

Uygulamayı çalıştırın ve db'nin dağıtıldığını doğrulayın.

Veritabanını inceleme

VERITABANıNı incelemek için SQL Server Nesne Gezgini kullanın. Tablo eklemeye __EFMigrationsHistory dikkat edin. Tablo, __EFMigrationsHistory db'ye hangi geçişlerin uygulandığını izler. Tablodaki __EFMigrationsHistory verileri görüntülediğinizde, ilk geçiş için bir satır gösterilir. Önceki CLI çıkış örneğindeki son günlük, bu satırı oluşturan INSERT deyimini gösterir.

Uygulamayı çalıştırın ve her şeyin çalıştığını doğrulayın.

Üretimde geçişleri uygulama

Üretim uygulamalarının uygulama başlangıcında Database.Migrate'ı çağırmaması önerilir. Migrate sunucu grubundaki bir uygulamadan çağrılmamalıdır. Örneğin, uygulama ölçeği genişletme ile buluta dağıtıldıysa (uygulamanın birden çok örneği çalışıyor).

Veritabanı geçişi, dağıtımın bir parçası olarak ve denetimli bir şekilde yapılmalıdır. Üretim veritabanı geçiş yaklaşımları şunlardır:

  • SQL betikleri oluşturmak için geçişleri kullanma ve dağıtımda SQL betiklerini kullanma.
  • Denetimli bir ortamdan çalıştırma dotnet ef database update .

EF Core , herhangi bir geçişin __MigrationsHistory çalıştırılması gerekip gerekmediğini görmek için tabloyu kullanır. Veritabanı güncelse hiçbir geçiş çalıştırılır.

Sorun giderme

Tamamlanmış uygulamayı indirin.

Uygulama aşağıdaki özel durumu oluşturur:

SqlException: Cannot open database "ContosoUniversity" requested by the login.
The login failed.
Login failed for user 'user name'.

Çözüm: Çalıştır dotnet ef database update

Ek kaynaklar