Öğretici: ASP.NET MVC 5 uygulamasında EF ile Devralma Uygulama

Önceki öğreticide eşzamanlılık özel durumlarını işlediyseniz. Bu öğreticide veri modelinde devralmayı nasıl uygulayacağınız gösterilir.

Nesne odaklı programlamada, kodun yeniden kullanımını kolaylaştırmak için devralmayı kullanabilirsiniz. Bu öğreticide ve sınıflarını değiştirerek Instructor hem eğitmenler hem de öğrenciler için ortak özellikler içeren LastName bir Person temel sınıftan türetilir.Student Hiçbir web sayfası eklemez veya değiştirmezsiniz, ancak kodun bir bölümünü değiştirirsiniz ve bu değişiklikler otomatik olarak veritabanına yansıtılır.

Bu öğreticide şunları yaptınız:

  • Devralmayı veritabanına eşlemeyi öğrenin
  • Person sınıfını oluşturma
  • Eğitmeni ve Öğrenciyi Güncelleştirme
  • Modele Kişi Ekleme
  • Geçişleri Oluşturma ve Güncelleştirme
  • Uygulamayı test etme
  • Azure’a dağıtın

Önkoşullar

Devralmayı veritabanına eşleme

Instructor Veri modelindeki School ve Student sınıfları aynı olan çeşitli özelliklere sahiptir:

Student_and_Instructor_classes

ve Student varlıkları tarafından Instructor paylaşılan özellikler için yedekli kodu ortadan kaldırmak istediğinizi varsayalım. Ya da adın bir eğitmenden mi yoksa öğrenciden mi geldiğiyle ilgilenmeden adları biçimlendirebilen bir hizmet yazmak istiyorsunuz. Yalnızca bu paylaşılan özellikleri içeren bir Person temel sınıf oluşturabilir, ardından aşağıdaki çizimde gösterildiği gibi ve Student varlıklarının bu temel sınıftan devralınır hale getirebilirsinizInstructor:

Student_and_Instructor_classes_deriving_from_Person_class

Bu devralma yapısının veritabanında temsil edilebileceği çeşitli yollar vardır. Tek bir Person tabloda hem öğrenciler hem de eğitmenler hakkında bilgi içeren bir tablonuz olabilir. Sütunların bazıları yalnızca eğitmenlere (HireDate ), bazıları yalnızca öğrencilere (EnrollmentDate ), bazıları her ikisine de (LastName, FirstName) uygulanabilir. Normalde, her satırın hangi türü temsil ettiğini belirten bir ayırıcı sütuna sahip olursunuz. Örneğin, ayrımcı sütunda eğitmenler için "Eğitmen" ve öğrenciler için "Öğrenci" olabilir.

hierarchy_example başına tablo

Tek bir veritabanı tablosundan varlık devralma yapısı oluşturma deseni , hiyerarşi başına tablo (TPH) devralma olarak adlandırılır.

Alternatif olarak veritabanının devralma yapısına daha çok benzediğinden emin olabilirsiniz. Örneğin, tabloda yalnızca ad alanları ve tarih alanları Person olan ayrı Instructor ve Student tablolarınız olabilir.

type_inheritance başına tablo

Her varlık sınıfı için veritabanı tablosu yapma deseni , tür başına tablo (TPT) devralma olarak adlandırılır.

Diğer bir seçenek de soyut olmayan tüm türleri tek tek tablolara eşlemektir. Devralınan özellikler de dahil olmak üzere bir sınıfın tüm özellikleri, ilgili tablonun sütunlarıyla eşler. Bu desen, Somut Sınıf Başına Tablo (TPC) devralma olarak adlandırılır. Daha önce gösterildiği gibi , Studentve sınıfları için PersonTPC devralmayı uyguladıysanız, Student devralma uygulandıktan sonra ve Instructor tabloları öncekinden farklı Instructor görünmeyecektir.

TPC ve TPH devralma desenleri genellikle Entity Framework'te TPT devralma desenlerine göre daha iyi performans sunar, çünkü TPT desenleri karmaşık birleştirme sorgularında sonuçlanabilir.

Bu öğreticide TPH devralmayı uygulama gösterilmektedir. TPH, Entity Framework'teki varsayılan devralma desenidir, bu nedenle tek yapmanız gereken bir Person sınıf oluşturmak, ve Student sınıflarını öğesinden Persontüretecek şekilde değiştirmekInstructor, yeni sınıfı öğesine DbContexteklemek ve bir geçiş oluşturmaktır. (Diğer devralma desenlerini uygulama hakkında bilgi için MSDN Entity Framework belgelerinde Tür Başına Tablo (TPT) Devralmayı Eşleme ve Somut Sınıf Başına Tablo (TPC) Devralmayı Eşleme bölümüne bakın.)

Person sınıfını oluşturma

Models klasöründe Person.cs dosyasını oluşturun ve şablon kodunu aşağıdaki kodla değiştirin:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
    public abstract class Person
    {
        public int ID { get; set; }

        [Required]
        [StringLength(50)]
        [Display(Name = "Last Name")]
        public string LastName { get; set; }
        [Required]
        [StringLength(50, ErrorMessage = "First name cannot be longer than 50 characters.")]
        [Column("FirstName")]
        [Display(Name = "First Name")]
        public string FirstMidName { get; set; }

        [Display(Name = "Full Name")]
        public string FullName
        {
            get
            {
                return LastName + ", " + FirstMidName;
            }
        }
    }
}

Eğitmeni ve Öğrenciyi Güncelleştirme

Şimdi Person.sc değerleri devralmak için Instructor.cs ve Student.cs'yigüncelleştirin.

Instructor.cs dosyasında sınıfı sınıfından InstructorPerson türetin ve anahtar ve ad alanlarını kaldırın. Kod aşağıdaki örneğe benzer olacaktır:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
    public class Instructor : Person
    {
        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        [Display(Name = "Hire Date")]
        public DateTime HireDate { get; set; }

        public virtual ICollection<Course> Courses { get; set; }
        public virtual OfficeAssignment OfficeAssignment { get; set; }
    }
}

Student.cs dosyasında da benzer değişiklikler yapın. Student sınıfı aşağıdaki örneğe benzer olacaktır:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
    public class Student : Person
    {
        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        [Display(Name = "Enrollment Date")]
        public DateTime EnrollmentDate { get; set; }

        public virtual ICollection<Enrollment> Enrollments { get; set; }
    }
}

Modele Kişi Ekleme

SchoolContext.cs içinde varlık türü için Person bir DbSet özellik ekleyin:

public DbSet<Person> People { get; set; }

Entity Framework'ün hiyerarşi başına tablo devralmayı yapılandırmak için ihtiyaç duyduğu tek şey budur. Gördüğünüz gibi veritabanı güncelleştirildiğinde ve Instructor tablolarının Student yerine bir Person tablo olur.

Geçişleri Oluşturma ve Güncelleştirme

Paket Yöneticisi Konsolu'nda (PMC) aşağıdaki komutu girin:

Add-Migration Inheritance

Update-Database PMC'de komutunu çalıştırın. Geçişlerin nasıl işlendiğini bilmediği mevcut verilerimiz olduğundan komut bu noktada başarısız olur. Aşağıdakine benzer bir hata iletisi alırsınız:

'dbo nesnesi bırakılamadı. Yabancı ANAHTAR kısıtlaması tarafından başvurulacağından eğitmenin.

Open Migrations< timestamp>_Inheritance.cs ve yöntemini aşağıdaki kodla değiştirinUp:

public override void Up()
{
    // Drop foreign keys and indexes that point to tables we're going to drop.
    DropForeignKey("dbo.Enrollment", "StudentID", "dbo.Student");
    DropIndex("dbo.Enrollment", new[] { "StudentID" });

    RenameTable(name: "dbo.Instructor", newName: "Person");
    AddColumn("dbo.Person", "EnrollmentDate", c => c.DateTime());
    AddColumn("dbo.Person", "Discriminator", c => c.String(nullable: false, maxLength: 128, defaultValue: "Instructor"));
    AlterColumn("dbo.Person", "HireDate", c => c.DateTime());
    AddColumn("dbo.Person", "OldId", c => c.Int(nullable: true));

    // Copy existing Student data into new Person table.
    Sql("INSERT INTO dbo.Person (LastName, FirstName, HireDate, EnrollmentDate, Discriminator, OldId) SELECT LastName, FirstName, null AS HireDate, EnrollmentDate, 'Student' AS Discriminator, ID AS OldId FROM dbo.Student");

    // Fix up existing relationships to match new PK's.
    Sql("UPDATE dbo.Enrollment SET StudentId = (SELECT ID FROM dbo.Person WHERE OldId = Enrollment.StudentId AND Discriminator = 'Student')");

    // Remove temporary key
    DropColumn("dbo.Person", "OldId");

    DropTable("dbo.Student");

    // Re-create foreign keys and indexes pointing to new table.
    AddForeignKey("dbo.Enrollment", "StudentID", "dbo.Person", "ID", cascadeDelete: true);
    CreateIndex("dbo.Enrollment", "StudentID");
}

Bu kod aşağıdaki veritabanı güncelleştirme görevlerini üstlenir:

  • Student tablosuna işaret eden yabancı anahtar kısıtlamalarını ve dizinlerini kaldırır.

  • Eğitmen tablosunu Kişi olarak yeniden adlandırır ve Öğrenci verilerini depolamak için gerekli değişiklikleri yapar:

    • Öğrenciler için null atanabilir EnrollmentDate ekler.
    • Bir satırın öğrenciye mi yoksa eğitmene mi yönelik olduğunu belirtmek için Ayrımcı sütunu ekler.
    • Öğrenci satırlarının işe alma tarihleri olmayacağından HireDate değerini null yapılabilir hale getirir.
    • Öğrencilere işaret eden yabancı anahtarları güncelleştirmek için kullanılacak geçici bir alan ekler. Öğrencileri Kişi tablosuna kopyaladığınızda, yeni birincil anahtar değerleri elde ederler.
  • Öğrenci tablosundaki verileri Kişi tablosuna kopyalar. Bu, öğrencilere yeni birincil anahtar değerleri atanmalarına neden olur.

  • Öğrencilere işaret eden yabancı anahtar değerlerini düzeltir.

  • Yabancı anahtar kısıtlamalarını ve dizinlerini yeniden oluşturarak bunları Kişi tablosuna yönlendirir.

(Birincil anahtar türü olarak tamsayı yerine GUID kullandıysanız, öğrencinin birincil anahtar değerlerinin değişmesi gerekmez ve bu adımlardan bazıları atlanabilirdi.)

update-database komutunu yeniden çalıştırın.

(Bir üretim sisteminde, önceki veritabanı sürümüne geri dönmek için bunu kullanmanız gerekme ihtimaline karşı Down yönteminde ilgili değişiklikleri yaparsınız. Bu öğreticide Down yöntemini kullanmayacaksınız.)

Not

Verileri geçirirken ve şema değişiklikleri yaparken başka hatalar almak mümkündür. Çözemediğiniz geçiş hataları alırsanız, Web.config dosyasındaki bağlantı dizesi değiştirerek veya veritabanını silerek öğreticiye devam edebilirsiniz. En basit yaklaşım, veritabanınıWeb.config dosyasında yeniden adlandırmaktır. Örneğin, aşağıdaki örnekte gösterildiği gibi veritabanı adını ContosoUniversity2 olarak değiştirin:

<add name="SchoolContext" 
    connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=ContosoUniversity2;Integrated Security=SSPI;" 
    providerName="System.Data.SqlClient" />

Yeni bir veritabanıyla geçirecek veri yoktur ve komutun update-database hatasız tamamlanma olasılığı çok daha yüksektir. Veritabanını silme yönergeleri için bkz. Visual Studio 2012'den Veritabanı Bırakma. Öğreticiye devam etmek için bu yaklaşımı benimserseniz, bu öğreticinin sonundaki dağıtım adımını atlayın veya yeni bir siteye ve veritabanına dağıtın. Bir güncelleştirmeyi zaten dağıtmakta olduğunuz siteye dağıtırsanız EF, geçişleri otomatik olarak çalıştırdığında aynı hatayı orada alır. Geçiş hatasını gidermek istiyorsanız, en iyi kaynak Entity Framework forumlarından veya StackOverflow.com biridir.

Uygulamayı test etme

Siteyi çalıştırın ve çeşitli sayfaları deneyin. Her şey daha önce olduğu gibi çalışır.

Sunucu Gezgini'ndeVeri Bağlantıları\SchoolContext ve ardından Tablolar'ı genişletin; Öğrenci ve Eğitmen tablolarının bir Kişi tablosuyla değiştirildiğini görürsünüz. Kişi tablosunu genişletirseniz, öğrenci ve eğitmen tablolarında kullanılan tüm sütunların bulunduğunu görürsünüz.

Kişi tablosuna sağ tıklayın ve sonra ayrımcı sütunu görmek için Tablo Verilerini Göster'e tıklayın.

Aşağıdaki diyagramda yeni School veritabanının yapısı gösterilmektedir:

School_database_diagram

Azure’a dağıtın

Bu bölüm, bu öğretici serisinin 3. Bölüm, Sıralama, Filtreleme ve Sayfalama bölümündeki isteğe bağlı Uygulamayı Azure'a dağıtma bölümünü tamamlamanızı gerektirir. Yerel projenizdeki veritabanını silerek çözdüğünüz geçiş hataları varsa bu adımı atlayın; veya yeni bir site ve veritabanı oluşturun ve yeni ortama dağıtın.

  1. Visual Studio'da, Çözüm Gezgini'da projeye sağ tıklayın ve bağlam menüsünden Yayımla'yı seçin.

  2. Yayımla’ya tıklayın.

    Web uygulaması varsayılan tarayıcınızda açılır.

  3. Çalıştığını doğrulamak için uygulamayı test edin.

    Veritabanına erişen bir sayfayı ilk kez çalıştırdığınızda, Entity Framework veritabanını geçerli veri modeliyle güncel yapmak için gereken tüm geçiş Up yöntemlerini çalıştırır.

Kodu alma

Tamamlanan Projeyi İndir

Ek kaynaklar

Diğer Entity Framework kaynaklarına bağlantılar ASP.NET Veri Erişimi - Önerilen Kaynaklar bölümünde bulunabilir.

Bu ve diğer devralma yapıları hakkında daha fazla bilgi için bkz. MSDN'de TPT Devralma Düzeni ve TPH Devralma Düzeni . Sonraki öğreticide, görece gelişmiş çeşitli Entity Framework senaryolarını işlemeyi öğreneceksiniz.

Sonraki adımlar

Bu öğreticide şunları yaptınız:

  • Devralmayı veritabanına eşlemeyi öğrendin
  • Person sınıfı oluşturuldu
  • Güncelleştirilmiş Eğitmen ve Öğrenci
  • Modele Kişi Eklendi
  • Oluşturulan ve Güncelleştirilen Geçişler
  • Uygulamayı test etti
  • Azure'a dağıtıldı

Entity Framework Code First kullanan ASP.NET web uygulamaları geliştirmenin temellerini aştığınızda dikkat etmeniz gereken konular hakkında bilgi edinmek için sonraki makaleye ilerleyin.