Öğretici: Karmaşık veri modeli oluşturma - ile MVC ASP.NET EF Core

Önceki öğreticilerde üç varlık içeren basit bir veri modeliyle çalıştınız. Bu öğreticide daha fazla varlık ve ilişki ekleyecek ve biçimlendirme, doğrulama ve veritabanı eşleme kurallarını belirterek veri modelini özelleştireceksiniz.

İşiniz bittiğinde varlık sınıfları, aşağıdaki çizimde gösterilen tamamlanmış veri modelini oluşturur:

Entity diagram

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

  • Veri modelini özelleştirme
  • Öğrenci varlığında değişiklik yapma
  • Eğitmen varlığı oluşturma
  • OfficeAssignment varlığı oluşturma
  • Course varlığını değiştirme
  • Departman varlığı oluşturma
  • Kayıt varlığını değiştirme
  • Veritabanı bağlamını güncelleştirme
  • Test verileriyle tohum veritabanı
  • Geçiş ekleme
  • bağlantı dizesi değiştirme
  • Veritabanını güncelleştirme

Ön koşullar

Veri modelini özelleştirme

Bu bölümde biçimlendirme, doğrulama ve veritabanı eşleme kurallarını belirten öznitelikleri kullanarak veri modelini özelleştirmeyi öğreneceksiniz. Ardından, aşağıdaki bölümlerde zaten oluşturduğunuz sınıflara öznitelikler ekleyerek ve modeldeki kalan varlık türleri için yeni sınıflar oluşturarak school veri modelinin tamamını oluşturacaksınız.

DataType özniteliği

Öğrenci kayıt tarihleri için, tüm web sayfaları şu anda tarihle birlikte saati görüntüler, ancak bu alan için tek ilgilendiğiniz tarihtir. Veri ek açıklaması özniteliklerini kullanarak, verileri gösteren her görünümde görüntüleme biçimini düzeltecek bir kod değişikliği yapabilirsiniz. Bunun nasıl yapıldığını gösteren bir örnek görmek için sınıfındaki Student özelliğine EnrollmentDate bir öznitelik ekleyeceksiniz.

içindeModels/Student.cs, aşağıdaki örnekte gösterildiği gibi ad alanı için System.ComponentModel.DataAnnotations bir using deyim ekleyin ve özelliğine EnrollmentDate ve DisplayFormat öznitelikleri ekleyinDataType:

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

namespace ContosoUniversity.Models
{
    public class Student
    {
        public int ID { get; set; }
        public string LastName { get; set; }
        public string FirstMidName { get; set; }
        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        public DateTime EnrollmentDate { get; set; }

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

DataType özniteliği, veritabanı iç türünden daha özel bir veri türü belirtmek için kullanılır. Bu durumda, tarih ve saati değil yalnızca tarihi izlemek istiyoruz. Numaralandırma TarihDataType, Saat, Telefon Number, Para Birimi, EmailAddress ve daha fazlası gibi birçok veri türü sağlar. Özniteliği, DataType uygulamanın türe özgü özellikleri otomatik olarak sağlamasına da olanak sağlayabilir. Örneğin, için DataType.EmailAddressbir mailto: bağlantı oluşturulabilir ve HTML5'i destekleyen tarayıcılarda için DataType.Date bir tarih seçici sağlanabilir. özniteliği, DataType HTML 5 data- tarayıcılarının anlayabileceği HTML 5 (belirgin veri tiresi) öznitelikleri yayar. DataType Öznitelikler herhangi bir doğrulama sağlamaz.

DataType.Date görüntülenen tarihin biçimini belirtmez. Varsayılan olarak, veri alanı sunucunun CultureInfo'sunu temel alan varsayılan biçimlere göre görüntülenir.

DisplayFormat özniteliği, tarih biçimini açıkça belirtmek için kullanılır:

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]

ayarı, ApplyFormatInEditMode değer düzenleme için bir metin kutusunda görüntülendiğinde biçimlendirmenin de uygulanması gerektiğini belirtir. (Bazı alanlarda bunu istemeyebilirsiniz; örneğin para birimi değerleri için, metin kutusunda para birimi simgesinin düzenlenmesini istemeyebilirsiniz.)

özniteliğini DisplayFormat tek başına kullanabilirsiniz, ancak özniteliğini DataType de kullanmak genellikle iyi bir fikirdir. DataType özniteliği, verilerin ekranda nasıl işlendiğinin aksine semantiğini iletir ve ile DisplayFormatelde etmediğiniz aşağıdaki avantajları sağlar:

  • Tarayıcı HTML5 özelliklerini etkinleştirebilir (örneğin, bir takvim denetimi, yerel ayara uygun para birimi simgesi, e-posta bağlantıları, istemci tarafı giriş doğrulaması vb.) gösterebilir.

  • Varsayılan olarak, tarayıcı yerel ayarınıza göre doğru biçimi kullanarak verileri işler.

Daha fazla bilgi için giriş etiketi yardımcı belgelerine bakın<.>

Uygulamayı çalıştırın, Öğrenci Dizini sayfasına gidin ve kayıt tarihleri için artık saatlerin görüntülenmediğini fark edin. Öğrenci modelini kullanan tüm görünümler için de aynı şey geçerli olacaktır.

Students index page showing dates without times

StringLength özniteliği

Ayrıca öznitelikleri kullanarak veri doğrulama kuralları ve doğrulama hata iletileri belirtebilirsiniz. StringLength özniteliği veritabanındaki uzunluk üst sınırını ayarlar ve ASP.NET Core MVC için istemci tarafı ve sunucu tarafı doğrulaması sağlar. Bu öznitelikte en düşük dize uzunluğunu da belirtebilirsiniz, ancak en düşük değerin veritabanı şeması üzerinde hiçbir etkisi yoktur.

Kullanıcıların bir ad için 50'den fazla karakter girmediğinden emin olmak istediğinizi varsayalım. Bu sınırlamayı eklemek içinLastName, aşağıdaki örnekte gösterildiği gibi ve FirstMidName özelliklerine öznitelikler ekleyinStringLength:

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

namespace ContosoUniversity.Models
{
    public class Student
    {
        public int ID { get; set; }
        [StringLength(50)]
        public string LastName { get; set; }
        [StringLength(50)]
        public string FirstMidName { get; set; }
        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        public DateTime EnrollmentDate { get; set; }

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

StringLength özniteliği, kullanıcının bir ad için boşluk girmesini engellemez. Girişe RegularExpression kısıtlamalar uygulamak için özniteliğini kullanabilirsiniz. Örneğin, aşağıdaki kod ilk karakterin büyük harf olmasını ve kalan karakterlerin alfabetik olmasını gerektirir:

[RegularExpression(@"^[A-Z]+[a-zA-Z]*$")]

özniteliği, MaxLength özniteliğine StringLength benzer işlevler sağlar ancak istemci tarafı doğrulaması sağlamaz.

Veritabanı modeli artık veritabanı şemasında değişiklik gerektirecek şekilde değişmiştir. Uygulama kullanıcı arabirimini kullanarak veritabanına eklemiş olabileceğiniz verileri kaybetmeden şemayı güncelleştirmek için geçişleri kullanacaksınız.

Değişikliklerinizi kaydedin ve projeyi oluşturun. Ardından proje klasöründeki komut penceresini açın ve aşağıdaki komutları girin:

dotnet ef migrations add MaxLengthOnNames
dotnet ef database update

Komutu migrations add , değişiklik iki sütun için uzunluk üst sınırını kısalttığı için veri kaybı olabileceği konusunda uyarır. Migrations adlı <timeStamp>_MaxLengthOnNames.csbir dosya oluşturur. Bu dosya yönteminde Up veritabanını geçerli veri modeliyle eşleşecek şekilde güncelleştirecek kod içerir. Komut database update bu kodu çalıştırmıştı.

Geçişler dosya adına ön ekli zaman damgası, Entity Framework tarafından geçişleri sıralamak için kullanılır. update-database komutunu çalıştırmadan önce birden çok geçiş oluşturabilirsiniz ve sonra tüm geçişler oluşturuldukları sırayla uygulanır.

Uygulamayı çalıştırın, Öğrenciler sekmesini seçin, Yeni Oluştur'a tıklayın ve 50 karakterden uzun bir ad girmeyi deneyin. Uygulama bunu yapmanıza engel olmalıdır.

Column özniteliği

Sınıflarınızın ve özelliklerinizin veritabanına nasıl eşlenmiş olduğunu denetlemek için öznitelikleri de kullanabilirsiniz. Alan ikinci ad da içerebileceğinden, ad alanı için adı kullandığınızı FirstMidName varsayalım. Ancak, veritabanına geçici sorgular yazacak kullanıcılar bu ada alışkın olduğundan veritabanı sütununun olarak adlandırılmasını FirstNameistiyorsunuz. Bu eşlemeyi yapmak için özniteliğini Column kullanabilirsiniz.

Column özniteliği, veritabanı oluşturulduğunda, özelliğine eşleyen tablonun sütununun StudentFirstMidName olarak adlandırılacağını FirstNamebelirtir. Başka bir deyişle, kodunuz öğesine başvurduğunda Student.FirstMidNameveriler tablosundan FirstName gelir veya tablonun sütununda Student güncelleştirilir. Sütun adlarını belirtmezseniz, bunlara özellik adıyla aynı ad verilir.

Student.cs Dosyasında, aşağıdaki vurgulanmış kodda gösterildiği gibi için System.ComponentModel.DataAnnotations.Schema bir using deyimi ekleyin ve özelliğine FirstMidName sütun adı özniteliğini ekleyin:

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

namespace ContosoUniversity.Models
{
    public class Student
    {
        public int ID { get; set; }
        [StringLength(50)]
        public string LastName { get; set; }
        [StringLength(50)]
        [Column("FirstName")]
        public string FirstMidName { get; set; }
        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        public DateTime EnrollmentDate { get; set; }

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

özniteliğinin Column eklenmesi, veritabanının eşleşmemesi için öğesinin desteklenmesine SchoolContextneden olan modeli değiştirir.

Değişikliklerinizi kaydedin ve projeyi oluşturun. Ardından proje klasöründeki komut penceresini açın ve başka bir geçiş oluşturmak için aşağıdaki komutları girin:

dotnet ef migrations add ColumnFirstName
dotnet ef database update

SQL Server Nesne Gezgini'da Öğrenci tablosu tasarımcısına çift tıklayarak Öğrenci tablosu tasarımcısını açın.

Students table in SSOX after migrations

İlk iki geçişi uygulamadan önce ad sütunları nvarchar(MAX) türündeydi. Bunlar artık nvarchar(50) ve sütun adı FirstMidName olan FirstName olarak değiştirildi.

Dekont

Aşağıdaki bölümlerde tüm varlık sınıflarını oluşturmayı tamamlamadan önce derlemeyi denerseniz, derleyici hataları alabilirsiniz.

Öğrenci varlığındaki değişiklikler

Student entity

içinde Models/Student.cs, daha önce eklediğiniz kodu aşağıdaki kodla değiştirin. Değişiklikler vurgulanır.

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

namespace ContosoUniversity.Models
{
    public class Student
    {
        public int ID { get; set; }
        [Required]
        [StringLength(50)]
        [Display(Name = "Last Name")]
        public string LastName { get; set; }
        [Required]
        [StringLength(50)]
        [Column("FirstName")]
        [Display(Name = "First Name")]
        public string FirstMidName { get; set; }
        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        [Display(Name = "Enrollment Date")]
        public DateTime EnrollmentDate { get; set; }
        [Display(Name = "Full Name")]
        public string FullName
        {
            get
            {
                return LastName + ", " + FirstMidName;
            }
        }

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

Gerekli özniteliği

özniteliği, Required ad özelliklerini gerekli alanlara getirir. Required Öznitelik, değer türleri (DateTime, int, double, float vb.) gibi null atanamayan türler için gerekli değildir. Null yapılamaz türler otomatik olarak gerekli alanlar olarak kabul edilir.

özniteliğinin Required uygulanabilmesi için MinimumLength ile MinimumLength kullanılması gerekir.

[Display(Name = "Last Name")]
[Required]
[StringLength(50, MinimumLength=2)]
public string LastName { get; set; }

Display özniteliği

özniteliği, Display metin kutuları için başlık her örnekteki özellik adı yerine "Ad", "Soyadı", "Tam Ad" ve "Kayıt Tarihi" olması gerektiğini belirtir (sözcükleri bölen bir alanı yoktur).

FullName hesaplanan özelliği

FullName , diğer iki özelliğin birleştirilmesiyle oluşturulan bir değer döndüren hesaplanmış bir özelliktir. Bu nedenle yalnızca bir get erişimcisine sahiptir ve veritabanında hiçbir FullName sütun oluşturulmaz.

Eğitmen varlığı oluşturma

Instructor entity

şablon kodunu aşağıdaki kodla değiştirerek oluşturun Models/Instructor.cs:

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

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

        [Required]
        [Display(Name = "Last Name")]
        [StringLength(50)]
        public string LastName { get; set; }

        [Required]
        [Column("FirstName")]
        [Display(Name = "First Name")]
        [StringLength(50)]
        public string FirstMidName { get; set; }

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

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

        public ICollection<CourseAssignment> CourseAssignments { get; set; }
        public OfficeAssignment OfficeAssignment { get; set; }
    }
}

Öğrenci ve Eğitmen varlıklarında birkaç özelliğin aynı olduğuna dikkat edin. Bu serinin devamında yer alan Devralma Uygulama öğreticisinde, yedekliliği ortadan kaldırmak için bu kodu yeniden düzenleyeceksiniz.

Bir satıra birden çok öznitelik koyarak öznitelikleri aşağıdaki gibi de yazabilirsiniz HireDate :

[DataType(DataType.Date),Display(Name = "Hire Date"),DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]

CourseAssignments ve OfficeAssignment gezinti özellikleri

CourseAssignments ve OfficeAssignment özellikleri gezinti özellikleridir.

Eğitmen herhangi bir sayıda ders verebilir, bu nedenle CourseAssignments koleksiyon olarak tanımlanır.

public ICollection<CourseAssignment> CourseAssignments { get; set; }

Gezinti özelliği birden çok varlığı barındırabiliyorsa, bu özelliğin türü girdilerin eklenebileceği, silinebileceği ve güncelleştirilebileceği bir liste olmalıdır. veya veya gibi List<T>HashSet<T>bir tür belirtebilirsinizICollection<T>. belirtirseniz ICollection<T>, EF varsayılan olarak bir HashSet<T> koleksiyon oluşturur.

Bunların CourseAssignment varlık olmasının nedeni aşağıda çoka çok ilişkileri hakkında bölümünde açıklanmıştır.

Contoso Üniversitesi iş kuralları, bir eğitmenin yalnızca en fazla bir ofise sahip olabileceğini belirtir, bu nedenle özelliğin OfficeAssignment tek bir OfficeAssignment varlığı (herhangi bir ofis atanmazsa null olabilir).

public OfficeAssignment OfficeAssignment { get; set; }

OfficeAssignment varlığı oluşturma

OfficeAssignment entity

Aşağıdaki kodla oluşturun Models/OfficeAssignment.cs :

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

namespace ContosoUniversity.Models
{
    public class OfficeAssignment
    {
        [Key]
        public int InstructorID { get; set; }
        [StringLength(50)]
        [Display(Name = "Office Location")]
        public string Location { get; set; }

        public Instructor Instructor { get; set; }
    }
}

Key özniteliği

ve OfficeAssignment varlıkları arasında Instructor bire sıfır veya bir ilişkisi vardır. Bir ofis ataması yalnızca atandığı eğitmenle ilişkili olarak bulunur ve bu nedenle birincil anahtarı aynı zamanda varlığın Instructor yabancı anahtarıdır. Ancak adı veya classnameID adlandırma kuralına uymadığından Entity Framework bu varlığın ID birincil anahtarı olarak otomatik olarak tanıyamazInstructorID. Bu nedenle, Key özniteliği anahtar olarak tanımlamak için kullanılır:

[Key]
public int InstructorID { get; set; }

Varlığın Key kendi birincil anahtarı varsa ancak özelliğine classnameID veya ID dışında bir ad vermek istiyorsanız özniteliğini de kullanabilirsiniz.

Varsayılan olarak, sütun tanımlayıcı bir ilişki için olduğundan EF anahtarı veritabanı oluşturulmamış olarak ele alır.

Eğitmen gezinti özelliği

Eğitmen varlığı null atanabilir OfficeAssignment bir gezinti özelliğine sahiptir (bir eğitmenin office ataması olmayabilir) ve OfficeAssignment varlığı null atanamaz Instructor bir gezinti özelliğine sahiptir (bir office ataması eğitmen olmadan mevcut olmadığından) InstructorID null atanamaz. Eğitmen varlığının ilişkili bir OfficeAssignment varlığı olduğunda, her varlığın gezinti özelliğinde diğerine bir başvurusu olur.

İlgili bir eğitmen olması gerektiğini belirtmek için Eğitmen gezinti özelliğine bir [Required] öznitelik koyabilirsiniz, ancak yabancı anahtar (bu tablonun anahtarı da budur) null atanamaz olduğundan InstructorID bunu yapmanız gerekmez.

Course varlığını değiştirme

Course entity

içinde Models/Course.cs, daha önce eklediğiniz kodu aşağıdaki kodla değiştirin. Değişiklikler vurgulanır.

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

namespace ContosoUniversity.Models
{
    public class Course
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        [Display(Name = "Number")]
        public int CourseID { get; set; }

        [StringLength(50, MinimumLength = 3)]
        public string Title { get; set; }

        [Range(0, 5)]
        public int Credits { get; set; }

        public int DepartmentID { get; set; }

        public Department Department { get; set; }
        public ICollection<Enrollment> Enrollments { get; set; }
        public ICollection<CourseAssignment> CourseAssignments { get; set; }
    }
}

Kurs varlığı, ilgili Departman varlığına işaret eden bir yabancı anahtar özelliğine DepartmentID ve gezinti Department özelliğine sahiptir.

Entity Framework, ilgili bir varlık için gezinti özelliğine sahip olduğunuzda veri modelinize yabancı anahtar özelliği eklemenizi gerektirmez. EF, gerektiğinde veritabanında otomatik olarak yabancı anahtarlar oluşturur ve bunlar için gölge özellikler oluşturur. Ancak veri modelinde yabancı anahtarın olması güncelleştirmeleri daha basit ve daha verimli hale getirebilir. Örneğin, düzenlemek üzere bir Course varlık getirdiğinizde, Department bu varlığı yüklemezseniz varlık null olur, bu nedenle varlığı güncelleştirdiğinizde Course önce varlığı getirmeniz Department gerekir. Yabancı anahtar özelliği DepartmentID veri modeline dahil edildiğinde, güncelleştirmeden önce varlığı getirmeniz Department gerekmez.

DatabaseGenerated özniteliği

DatabaseGenerated özelliğindeki NoneCourseID parametresine sahip özniteliği, birincil anahtar değerlerinin veritabanı tarafından oluşturulmak yerine kullanıcı tarafından sağlandığını belirtir.

[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Name = "Number")]
public int CourseID { get; set; }

Varsayılan olarak, Entity Framework birincil anahtar değerlerinin veritabanı tarafından oluşturulduğunu varsayar. Çoğu senaryoda istediğiniz budur. Ancak varlıklar için, bir bölüm için Course 1000 serisi, başka bir bölüm için 2000 serisi gibi kullanıcı tarafından belirtilen bir kurs numarası kullanırsınız.

Öznitelik DatabaseGenerated , bir satırın oluşturulduğu veya güncelleştirildiği tarihi kaydetmek için kullanılan veritabanı sütunlarında olduğu gibi varsayılan değerleri oluşturmak için de kullanılabilir. Daha fazla bilgi için bkz . Oluşturulan Özellikler.

Yabancı anahtar ve gezinti özellikleri

Varlıktaki Course yabancı anahtar özellikleri ve gezinti özellikleri aşağıdaki ilişkileri yansıtır:

Kurs bir bölüme atandığından, yukarıda belirtilen nedenlerle bir DepartmentID yabancı anahtar ve Department gezinti özelliği vardır.

public int DepartmentID { get; set; }
public Department Department { get; set; }

Bir kursta kayıtlı herhangi bir sayıda öğrenci olabilir, bu nedenle Enrollments gezinti özelliği bir koleksiyondur:

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

Bir kurs birden çok eğitmen tarafından öğretilebilir, bu nedenle CourseAssignments gezinti özelliği bir koleksiyondur (türü CourseAssignment daha sonra açıklanmıştır):

public ICollection<CourseAssignment> CourseAssignments { get; set; }

Departman varlığı oluşturma

Department entity

Aşağıdaki kodla oluşturun Models/Department.cs :

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

namespace ContosoUniversity.Models
{
    public class Department
    {
        public int DepartmentID { get; set; }

        [StringLength(50, MinimumLength = 3)]
        public string Name { get; set; }

        [DataType(DataType.Currency)]
        [Column(TypeName = "money")]
        public decimal Budget { get; set; }

        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        [Display(Name = "Start Date")]
        public DateTime StartDate { get; set; }

        public int? InstructorID { get; set; }

        public Instructor Administrator { get; set; }
        public ICollection<Course> Courses { get; set; }
    }
}

Column özniteliği

Daha önce sütun adı eşlemesini değiştirmek için özniteliğini Column kullandınız. Varlığın kodunda Department , sql veri türü eşlemesini Column değiştirmek için özniteliği kullanılır, böylece sütun veritabanındaki SQL Server money türü kullanılarak tanımlanır:

[Column(TypeName="money")]
public decimal Budget { get; set; }

Varlık Çerçevesi özelliği için tanımladığınız CLR türüne göre uygun SQL Server veri türünü seçtiğinden sütun eşlemesi genellikle gerekli değildir. CLR decimal türü bir SQL Server decimal türüyle eşler. Ancak bu durumda, sütunun para birimi tutarlarını tutacağını ve para veri türünün bunun için daha uygun olduğunu biliyorsunuz.

Yabancı anahtar ve gezinti özellikleri

Yabancı anahtar ve gezinti özellikleri aşağıdaki ilişkileri yansıtır:

Bir bölümün yöneticisi olabilir veya olmayabilir ve yönetici her zaman eğitmendir. Bu nedenle InstructorID özellik, Eğitmen varlığının yabancı anahtarı olarak eklenir ve özelliği null atanabilir olarak işaretlemek için tür atamasının ardından int bir soru işareti eklenir. Gezinti özelliği adlandırılmıştır Administrator ancak bir Eğitmen varlığını barındırmaktadır:

public int? InstructorID { get; set; }
public Instructor Administrator { get; set; }

Bir bölümün birçok kursu olabileceği için Kurslar gezinti özelliği vardır:

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

Dekont

Kural gereği, Entity Framework null atanamayan yabancı anahtarlar ve çoka çok ilişkiler için art arda silmeyi etkinleştirir. Bu, döngüsel art arda silme kurallarına neden olabilir ve bu da geçiş eklemeye çalıştığınızda özel duruma neden olur. Örneğin, özelliğini null atanabilir olarak tanımlamadıysanız Department.InstructorID EF, eğitmeni sildiğinizde bölümü silmek için art arda silme kuralı yapılandırabilir. Bu, olmasını istediğiniz şey değildir. İş kurallarınız özelliğin InstructorID null atanamaz olmasını gerektiriyorsa, ilişkide art arda silmeyi devre dışı bırakmak için aşağıdaki akıcı API deyimini kullanmanız gerekir:

modelBuilder.Entity<Department>()
   .HasOne(d => d.Administrator)
   .WithMany()
   .OnDelete(DeleteBehavior.Restrict)

Kayıt varlığını değiştirme

Enrollment entity

içinde Models/Enrollment.cs, daha önce eklediğiniz kodu aşağıdaki kodla değiştirin:

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

namespace ContosoUniversity.Models
{
    public enum Grade
    {
        A, B, C, D, F
    }

    public class Enrollment
    {
        public int EnrollmentID { get; set; }
        public int CourseID { get; set; }
        public int StudentID { get; set; }
        [DisplayFormat(NullDisplayText = "No grade")]
        public Grade? Grade { get; set; }

        public Course Course { get; set; }
        public Student Student { get; set; }
    }
}

Yabancı anahtar ve gezinti özellikleri

Yabancı anahtar özellikleri ve gezinti özellikleri aşağıdaki ilişkileri yansıtır:

Kayıt kaydı tek bir kurs içindir, bu nedenle yabancı anahtar özelliği ve Course gezinti özelliği vardırCourseID:

public int CourseID { get; set; }
public Course Course { get; set; }

Kayıt kaydı tek bir öğrenciye yöneliktir, bu nedenle yabancı anahtar özelliği ve Student gezinti özelliği vardırStudentID:

public int StudentID { get; set; }
public Student Student { get; set; }

Çoka Çok ilişkileri

ve varlıkları arasında Student çoka çok ilişkisi vardır ve Enrollment varlık, veritabanında yükü olan çoka çok birleştirme tablosu işlevi Course görür. "Yük ile", tablonun birleştirilen tablolar için yabancı anahtarların (bu örnekte birincil anahtar ve Grade özellik) yanı sıra ek veriler içerdiği anlamına gelirEnrollment.

Aşağıdaki çizimde bu ilişkilerin bir varlık diyagramında nasıl göründüğü gösterilmektedir. (Bu diyagram EF 6.x için Entity Framework Power Tools kullanılarak oluşturulmuştur; diyagramı oluşturmak öğreticinin bir parçası değildir, yalnızca burada çizim olarak kullanılmaktadır.)

Student-Course many to many relationship

Her ilişki çizgisinin bir ucunda 1, diğer ucunda ise bire çok ilişkisini gösteren bir yıldız işareti (*) vardır.

Enrollment Tabloda not bilgileri yoksa, yalnızca ve iki yabancı anahtarı CourseIDStudentIDiçermesi gerekir. Bu durumda, veritabanında yükü (veya saf birleştirme tablosu) olmayan çoka çok birleştirme tablosu olur. Instructor ve Course varlıkları bu tür çoka çok ilişkisine sahiptir ve sonraki adımınız yük olmadan birleştirme tablosu olarak işlev görecek bir varlık sınıfı oluşturmaktır.

EF Core çoka çok ilişkiler için örtük birleştirme tablolarını destekler, ancak bu özel ders örtük birleştirme tablosu kullanacak şekilde güncelleştirilmemiştir. Bu öğreticinin Razor güncelleştirilen Sayfalar sürümü olan Çoka Çok İlişkiler'e bakın.

CourseAssignment varlığı

CourseAssignment entity

Aşağıdaki kodla oluşturun Models/CourseAssignment.cs :

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

namespace ContosoUniversity.Models
{
    public class CourseAssignment
    {
        public int InstructorID { get; set; }
        public int CourseID { get; set; }
        public Instructor Instructor { get; set; }
        public Course Course { get; set; }
    }
}

Varlık adlarını birleştirme

Veritabanında, Eğitmenden Kurslara çoka çok ilişkisi için bir birleştirme tablosu gereklidir ve bir varlık kümesiyle temsil edilmesi gerekir. Bir birleştirme varlığını EntityName1EntityName2adlandırmak yaygın bir işlemdir ve bu durumda olacaktır CourseInstructor. Ancak, ilişkiyi açıklayan bir ad seçmenizi öneririz. Veri modelleri basit bir şekilde başlar ve yükü olmayan birleştirmelerle daha sonra sık sık yük alır. Açıklayıcı bir varlık adıyla başlarsanız, adı daha sonra değiştirmeniz gerekmez. İdeal olarak, birleştirme varlığının iş etki alanında kendi doğal (muhtemelen tek sözcük) adı olabilir. Örneğin, Kitaplar ve Müşteriler Derecelendirmeler aracılığıyla bağlanabilir. Bu ilişki için, CourseAssignment değerinden CourseInstructordaha iyi bir seçimdir.

Bileşik anahtar

Yabancı anahtarlar null atanamaz ve birlikte tablonun her satırını benzersiz olarak tanımladığından ayrı bir birincil anahtara gerek yoktur. InstructorID ve CourseID özellikleri bileşik birincil anahtar olarak çalışmalıdır. EF'nin bileşik birincil anahtarlarını tanımlamanın tek yolu akıcı API'yi kullanmaktır (öznitelikler kullanılarak yapılamaz). Sonraki bölümde bileşik birincil anahtarı yapılandırmayı göreceksiniz.

Bileşik anahtar, bir kurs için birden çok satır ve bir eğitmen için birden çok satıra sahip olmanıza karşın, aynı eğitmen ve kurs için birden çok satıra sahip olamazsınız. Enrollment Birleştirme varlığı kendi birincil anahtarını tanımlar, bu nedenle bu sıralamanın yinelenenleri mümkündür. Bu tür yinelemeleri önlemek için yabancı anahtar alanlarına benzersiz bir dizin ekleyebilir veya benzeri CourseAssignmentbir birincil bileşik anahtarla yapılandırabilirsinizEnrollment. Daha fazla bilgi için bkz . Dizinler.

Veritabanı bağlamını güncelleştirme

Dosyaya aşağıdaki vurgulanmış kodu Data/SchoolContext.cs ekleyin:

using ContosoUniversity.Models;
using Microsoft.EntityFrameworkCore;

namespace ContosoUniversity.Data
{
    public class SchoolContext : DbContext
    {
        public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
        {
        }

        public DbSet<Course> Courses { get; set; }
        public DbSet<Enrollment> Enrollments { get; set; }
        public DbSet<Student> Students { get; set; }
        public DbSet<Department> Departments { get; set; }
        public DbSet<Instructor> Instructors { get; set; }
        public DbSet<OfficeAssignment> OfficeAssignments { get; set; }
        public DbSet<CourseAssignment> CourseAssignments { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Course>().ToTable("Course");
            modelBuilder.Entity<Enrollment>().ToTable("Enrollment");
            modelBuilder.Entity<Student>().ToTable("Student");
            modelBuilder.Entity<Department>().ToTable("Department");
            modelBuilder.Entity<Instructor>().ToTable("Instructor");
            modelBuilder.Entity<OfficeAssignment>().ToTable("OfficeAssignment");
            modelBuilder.Entity<CourseAssignment>().ToTable("CourseAssignment");

            modelBuilder.Entity<CourseAssignment>()
                .HasKey(c => new { c.CourseID, c.InstructorID });
        }
    }
}

Bu kod yeni varlıkları ekler ve CourseAssignment varlığının bileşik birincil anahtarını yapılandırılır.

Akıcı bir API alternatifi hakkında

sınıfının yöntemindeki OnModelCreatingDbContext kod, EF davranışını yapılandırmak için akıcı API'yi kullanır. Api'ye "fluent" adı verilir çünkü genellikle belgelerdeki EF Corebu örnekte olduğu gibi bir dizi yöntem çağrısını tek bir deyimde dizeleyerek kullanılır:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property(b => b.Url)
        .IsRequired();
}

Bu öğreticide, akıcı API'yi yalnızca özniteliklerle gerçekleştiremezseniz veritabanı eşlemesi için kullanıyorsunuz. Ancak, öznitelikleri kullanarak yapabileceğiniz biçimlendirme, doğrulama ve eşleme kurallarının çoğunu belirtmek için akıcı API'yi de kullanabilirsiniz. gibi MinimumLength bazı öznitelikler akıcı API ile uygulanamaz. Daha önce belirtildiği gibi şemayı MinimumLength değiştirmez, yalnızca istemci ve sunucu tarafı doğrulama kuralı uygular.

Bazı geliştiriciler, varlık sınıflarını "temiz" tutabilmek için yalnızca akıcı API'yi kullanmayı tercih eder. İsterseniz öznitelikleri ve akıcı API'yi karıştırabilirsiniz ve yalnızca akıcı API kullanılarak yapılabilecek birkaç özelleştirme vardır, ancak genel olarak önerilen yöntem bu iki yaklaşımdan birini seçmek ve bunu mümkün olduğunca tutarlı bir şekilde kullanmaktır. Her ikisini de kullanırsanız, çakışma olduğunda Fluent API'lerinin öznitelikleri geçersiz kıldığını unutmayın.

Öznitelikler ve akıcı API hakkında daha fazla bilgi için bkz . Yapılandırma yöntemleri.

İlişkileri Gösteren Varlık Diyagramı

Aşağıdaki çizimde, Tamamlanmış Okul modeli için Entity Framework Power Tools'un oluşturduğu diyagram gösterilmektedir.

Entity diagram

Bire çok ilişki çizgilerinin (1 -*) yanı sıra, burada ve varlıkları arasındaki bire sıfır veya bir ilişki çizgisini (1 -0,.1) ve OfficeAssignment Eğitmen ve Departman varlıkları arasındaki Instructor sıfır veya bire çok ilişki çizgisini (0,.1 - *) görebilirsiniz.

Test verileriyle tohum veritabanı

Oluşturduğunuz yeni varlıklar için tohum verileri sağlamak için dosyadaki kodu Data/DbInitializer.cs aşağıdaki kodla değiştirin.

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using ContosoUniversity.Models;

namespace ContosoUniversity.Data
{
    public static class DbInitializer
    {
        public static void Initialize(SchoolContext context)
        {
            //context.Database.EnsureCreated();

            // Look for any students.
            if (context.Students.Any())
            {
                return;   // DB has been seeded
            }

            var students = new Student[]
            {
                new Student { FirstMidName = "Carson",   LastName = "Alexander",
                    EnrollmentDate = DateTime.Parse("2010-09-01") },
                new Student { FirstMidName = "Meredith", LastName = "Alonso",
                    EnrollmentDate = DateTime.Parse("2012-09-01") },
                new Student { FirstMidName = "Arturo",   LastName = "Anand",
                    EnrollmentDate = DateTime.Parse("2013-09-01") },
                new Student { FirstMidName = "Gytis",    LastName = "Barzdukas",
                    EnrollmentDate = DateTime.Parse("2012-09-01") },
                new Student { FirstMidName = "Yan",      LastName = "Li",
                    EnrollmentDate = DateTime.Parse("2012-09-01") },
                new Student { FirstMidName = "Peggy",    LastName = "Justice",
                    EnrollmentDate = DateTime.Parse("2011-09-01") },
                new Student { FirstMidName = "Laura",    LastName = "Norman",
                    EnrollmentDate = DateTime.Parse("2013-09-01") },
                new Student { FirstMidName = "Nino",     LastName = "Olivetto",
                    EnrollmentDate = DateTime.Parse("2005-09-01") }
            };

            foreach (Student s in students)
            {
                context.Students.Add(s);
            }
            context.SaveChanges();

            var instructors = new Instructor[]
            {
                new Instructor { FirstMidName = "Kim",     LastName = "Abercrombie",
                    HireDate = DateTime.Parse("1995-03-11") },
                new Instructor { FirstMidName = "Fadi",    LastName = "Fakhouri",
                    HireDate = DateTime.Parse("2002-07-06") },
                new Instructor { FirstMidName = "Roger",   LastName = "Harui",
                    HireDate = DateTime.Parse("1998-07-01") },
                new Instructor { FirstMidName = "Candace", LastName = "Kapoor",
                    HireDate = DateTime.Parse("2001-01-15") },
                new Instructor { FirstMidName = "Roger",   LastName = "Zheng",
                    HireDate = DateTime.Parse("2004-02-12") }
            };

            foreach (Instructor i in instructors)
            {
                context.Instructors.Add(i);
            }
            context.SaveChanges();

            var departments = new Department[]
            {
                new Department { Name = "English",     Budget = 350000,
                    StartDate = DateTime.Parse("2007-09-01"),
                    InstructorID  = instructors.Single( i => i.LastName == "Abercrombie").ID },
                new Department { Name = "Mathematics", Budget = 100000,
                    StartDate = DateTime.Parse("2007-09-01"),
                    InstructorID  = instructors.Single( i => i.LastName == "Fakhouri").ID },
                new Department { Name = "Engineering", Budget = 350000,
                    StartDate = DateTime.Parse("2007-09-01"),
                    InstructorID  = instructors.Single( i => i.LastName == "Harui").ID },
                new Department { Name = "Economics",   Budget = 100000,
                    StartDate = DateTime.Parse("2007-09-01"),
                    InstructorID  = instructors.Single( i => i.LastName == "Kapoor").ID }
            };

            foreach (Department d in departments)
            {
                context.Departments.Add(d);
            }
            context.SaveChanges();

            var courses = new Course[]
            {
                new Course {CourseID = 1050, Title = "Chemistry",      Credits = 3,
                    DepartmentID = departments.Single( s => s.Name == "Engineering").DepartmentID
                },
                new Course {CourseID = 4022, Title = "Microeconomics", Credits = 3,
                    DepartmentID = departments.Single( s => s.Name == "Economics").DepartmentID
                },
                new Course {CourseID = 4041, Title = "Macroeconomics", Credits = 3,
                    DepartmentID = departments.Single( s => s.Name == "Economics").DepartmentID
                },
                new Course {CourseID = 1045, Title = "Calculus",       Credits = 4,
                    DepartmentID = departments.Single( s => s.Name == "Mathematics").DepartmentID
                },
                new Course {CourseID = 3141, Title = "Trigonometry",   Credits = 4,
                    DepartmentID = departments.Single( s => s.Name == "Mathematics").DepartmentID
                },
                new Course {CourseID = 2021, Title = "Composition",    Credits = 3,
                    DepartmentID = departments.Single( s => s.Name == "English").DepartmentID
                },
                new Course {CourseID = 2042, Title = "Literature",     Credits = 4,
                    DepartmentID = departments.Single( s => s.Name == "English").DepartmentID
                },
            };

            foreach (Course c in courses)
            {
                context.Courses.Add(c);
            }
            context.SaveChanges();

            var officeAssignments = new OfficeAssignment[]
            {
                new OfficeAssignment {
                    InstructorID = instructors.Single( i => i.LastName == "Fakhouri").ID,
                    Location = "Smith 17" },
                new OfficeAssignment {
                    InstructorID = instructors.Single( i => i.LastName == "Harui").ID,
                    Location = "Gowan 27" },
                new OfficeAssignment {
                    InstructorID = instructors.Single( i => i.LastName == "Kapoor").ID,
                    Location = "Thompson 304" },
            };

            foreach (OfficeAssignment o in officeAssignments)
            {
                context.OfficeAssignments.Add(o);
            }
            context.SaveChanges();

            var courseInstructors = new CourseAssignment[]
            {
                new CourseAssignment {
                    CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID,
                    InstructorID = instructors.Single(i => i.LastName == "Kapoor").ID
                    },
                new CourseAssignment {
                    CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID,
                    InstructorID = instructors.Single(i => i.LastName == "Harui").ID
                    },
                new CourseAssignment {
                    CourseID = courses.Single(c => c.Title == "Microeconomics" ).CourseID,
                    InstructorID = instructors.Single(i => i.LastName == "Zheng").ID
                    },
                new CourseAssignment {
                    CourseID = courses.Single(c => c.Title == "Macroeconomics" ).CourseID,
                    InstructorID = instructors.Single(i => i.LastName == "Zheng").ID
                    },
                new CourseAssignment {
                    CourseID = courses.Single(c => c.Title == "Calculus" ).CourseID,
                    InstructorID = instructors.Single(i => i.LastName == "Fakhouri").ID
                    },
                new CourseAssignment {
                    CourseID = courses.Single(c => c.Title == "Trigonometry" ).CourseID,
                    InstructorID = instructors.Single(i => i.LastName == "Harui").ID
                    },
                new CourseAssignment {
                    CourseID = courses.Single(c => c.Title == "Composition" ).CourseID,
                    InstructorID = instructors.Single(i => i.LastName == "Abercrombie").ID
                    },
                new CourseAssignment {
                    CourseID = courses.Single(c => c.Title == "Literature" ).CourseID,
                    InstructorID = instructors.Single(i => i.LastName == "Abercrombie").ID
                    },
            };

            foreach (CourseAssignment ci in courseInstructors)
            {
                context.CourseAssignments.Add(ci);
            }
            context.SaveChanges();

            var enrollments = new Enrollment[]
            {
                new Enrollment {
                    StudentID = students.Single(s => s.LastName == "Alexander").ID,
                    CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID,
                    Grade = Grade.A
                },
                    new Enrollment {
                    StudentID = students.Single(s => s.LastName == "Alexander").ID,
                    CourseID = courses.Single(c => c.Title == "Microeconomics" ).CourseID,
                    Grade = Grade.C
                    },
                    new Enrollment {
                    StudentID = students.Single(s => s.LastName == "Alexander").ID,
                    CourseID = courses.Single(c => c.Title == "Macroeconomics" ).CourseID,
                    Grade = Grade.B
                    },
                    new Enrollment {
                        StudentID = students.Single(s => s.LastName == "Alonso").ID,
                    CourseID = courses.Single(c => c.Title == "Calculus" ).CourseID,
                    Grade = Grade.B
                    },
                    new Enrollment {
                        StudentID = students.Single(s => s.LastName == "Alonso").ID,
                    CourseID = courses.Single(c => c.Title == "Trigonometry" ).CourseID,
                    Grade = Grade.B
                    },
                    new Enrollment {
                    StudentID = students.Single(s => s.LastName == "Alonso").ID,
                    CourseID = courses.Single(c => c.Title == "Composition" ).CourseID,
                    Grade = Grade.B
                    },
                    new Enrollment {
                    StudentID = students.Single(s => s.LastName == "Anand").ID,
                    CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID
                    },
                    new Enrollment {
                    StudentID = students.Single(s => s.LastName == "Anand").ID,
                    CourseID = courses.Single(c => c.Title == "Microeconomics").CourseID,
                    Grade = Grade.B
                    },
                new Enrollment {
                    StudentID = students.Single(s => s.LastName == "Barzdukas").ID,
                    CourseID = courses.Single(c => c.Title == "Chemistry").CourseID,
                    Grade = Grade.B
                    },
                    new Enrollment {
                    StudentID = students.Single(s => s.LastName == "Li").ID,
                    CourseID = courses.Single(c => c.Title == "Composition").CourseID,
                    Grade = Grade.B
                    },
                    new Enrollment {
                    StudentID = students.Single(s => s.LastName == "Justice").ID,
                    CourseID = courses.Single(c => c.Title == "Literature").CourseID,
                    Grade = Grade.B
                    }
            };

            foreach (Enrollment e in enrollments)
            {
                var enrollmentInDataBase = context.Enrollments.Where(
                    s =>
                            s.Student.ID == e.StudentID &&
                            s.Course.CourseID == e.CourseID).SingleOrDefault();
                if (enrollmentInDataBase == null)
                {
                    context.Enrollments.Add(e);
                }
            }
            context.SaveChanges();
        }
    }
}

İlk öğreticide gördüğünüz gibi, bu kodun çoğu yalnızca yeni varlık nesneleri oluşturur ve test için gereken örnek verileri özelliklere yükler. Çoka çok ilişkilerin nasıl işleneceğine dikkat edin: kod, ve CourseAssignment birleştirme varlık kümelerinde Enrollments varlıklar oluşturarak ilişkiler oluşturur.

Geçiş ekleme

Değişikliklerinizi kaydedin ve projeyi oluşturun. Ardından proje klasöründeki komut penceresini açın ve komutunu girin migrations add (update-database komutunu henüz yapmayın):

dotnet ef migrations add ComplexDataModel

Olası veri kaybıyla ilgili bir uyarı alırsınız.

An operation was scaffolded that may result in the loss of data. Please review the migration for accuracy.
Done. To undo this action, use 'ef migrations remove'

Komutu bu noktada çalıştırmaya database update çalıştıysanız (henüz uygulamayın), aşağıdaki hatayı alırsınız:

ALTER TABLE deyimi FOREIGN KEY kısıtlaması "FK_dbo. Course_dbo. Department_DepartmentID". Çakışma "ContosoUniversity" veritabanında, "dbo" tablosunda oluştu. Department", 'DepartmentID' sütunu.

Geçişleri var olan verilerle yürütürken bazen yabancı anahtar kısıtlamalarını karşılamak için saplama verilerini veritabanına eklemeniz gerekir. yönteminde oluşturulan kod, tabloya UpCourse null atanamaz DepartmentID bir yabancı anahtar ekler. Kod çalıştırıldığında Course tablosunda zaten satırlar varsa, AddColumn SQL Server sütuna null olmayan hangi değeri koyacağını bilmediğinden işlem başarısız olur. Bu öğreticide geçişi yeni bir veritabanında çalıştıracaksınız, ancak bir üretim uygulamasında geçişin mevcut verileri işlemesini sağlamanız gerekir, bu nedenle aşağıdaki yol tarifleri bunun nasıl yapıldığını gösteren bir örnek gösterir.

Bu geçişin var olan verilerle çalışmasını sağlamak için kodu değiştirerek yeni sütuna varsayılan bir değer vermeniz ve varsayılan departman görevi görmesi için "Temp" adlı bir saplama departmanı oluşturmanız gerekir. Sonuç olarak, yöntem çalıştırıldıktan sonra mevcut Kurs satırlarının tümü "Geçici" bölümle Up ilişkilendirilecektir.

  • {timestamp}_ComplexDataModel.cs dosyasını açın.

  • DepartmentID sütununu Course tablosuna ekleyen kod satırını açıklama satırına açıklama ekleyin.

    migrationBuilder.AlterColumn<string>(
        name: "Title",
        table: "Course",
        maxLength: 50,
        nullable: true,
        oldClrType: typeof(string),
        oldNullable: true);
                
    //migrationBuilder.AddColumn<int>(
    //    name: "DepartmentID",
    //    table: "Course",
    //    nullable: false,
    //    defaultValue: 0);
    
  • Department tablosunu oluşturan kodun arkasına aşağıdaki vurgulanmış kodu ekleyin:

    migrationBuilder.CreateTable(
        name: "Department",
        columns: table => new
        {
            DepartmentID = table.Column<int>(nullable: false)
                .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
            Budget = table.Column<decimal>(type: "money", nullable: false),
            InstructorID = table.Column<int>(nullable: true),
            Name = table.Column<string>(maxLength: 50, nullable: true),
            StartDate = table.Column<DateTime>(nullable: false)
        },
        constraints: table =>
        {
            table.PrimaryKey("PK_Department", x => x.DepartmentID);
            table.ForeignKey(
                name: "FK_Department_Instructor_InstructorID",
                column: x => x.InstructorID,
                principalTable: "Instructor",
                principalColumn: "ID",
                onDelete: ReferentialAction.Restrict);
        });
    
    migrationBuilder.Sql("INSERT INTO dbo.Department (Name, Budget, StartDate) VALUES ('Temp', 0.00, GETDATE())");
    // Default value for FK points to department created above, with
    // defaultValue changed to 1 in following AddColumn statement.
    
    migrationBuilder.AddColumn<int>(
        name: "DepartmentID",
        table: "Course",
        nullable: false,
        defaultValue: 1);
    

Üretim uygulamasında, Bölüm satırları eklemek ve Kurs satırlarını yeni Bölüm satırlarıyla ilişkilendirmek için kod veya betikler yazarsınız. Daha sonra artık sütundaki "Geçici" bölüme veya varsayılan değere Course.DepartmentID ihtiyacınız kalmaz.

Değişikliklerinizi kaydedin ve projeyi oluşturun.

bağlantı dizesi değiştirme

Artık sınıfında yeni DbInitializer varlıklar için boş bir veritabanına tohum verileri ekleyen yeni kodunuz var. EF'nin yeni bir boş veritabanı oluşturmasını sağlamak için içindeki bağlantı dizesi appsettings.json veritabanının adını ContosoUniversity3 olarak veya kullandığınız bilgisayarda kullanmadığınız başka bir adla değiştirin.

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=ContosoUniversity3;Trusted_Connection=True;MultipleActiveResultSets=true"
  },

Değişikliğinizi olarak appsettings.jsonkaydedin.

Dekont

Veritabanı adını değiştirmeye alternatif olarak, veritabanını silebilirsiniz. SQL Server Nesne Gezgini (SSOX) veya database drop CLI komutunu kullanın:

dotnet ef database drop

Veritabanını güncelleştirme

Veritabanı adını değiştirdikten veya veritabanını sildikten sonra, geçişleri yürütmek için komut penceresinde komutunu çalıştırın database update .

dotnet ef database update

Yönteminin yeni veritabanını çalıştırmasına ve doldurmasına neden olmak DbInitializer.Initialize için uygulamayı çalıştırın.

Daha önce yaptığınız gibi veritabanını SSOX'ta açın ve tüm tabloların oluşturulduğunu görmek için Tablolar düğümünü genişletin. (SSOX hala daha önceki bir zamanda açıksaYenile düğmesi.)

Tables in SSOX

Veritabanının çekirdeğini oluşturan başlatıcı kodunu tetikleyen uygulamayı çalıştırın.

CourseAssignment tablosuna sağ tıklayın ve içinde veri olduğunu doğrulamak için Verileri Görüntüle'yi seçin.

CourseAssignment data in SSOX

Kodu alma

Tamamlanan uygulamayı indirin veya görüntüleyin.

Sonraki adımlar

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

  • Veri modeli özelleştirilmiş
  • Öğrenci varlığında değişiklikler yapıldı
  • Eğitmen varlığı oluşturuldu
  • Oluşturulan OfficeAssignment varlığı
  • Değiştirilen Kurs varlığı
  • Departman varlığı oluşturuldu
  • Değiştirilen Kayıt varlığı
  • Veritabanı bağlamı güncelleştirildi
  • Test verileriyle dağıtılmış veritabanı
  • Geçiş eklendi
  • bağlantı dizesi değiştirildi
  • Veritabanı güncelleştirildi

İlgili verilere erişme hakkında daha fazla bilgi edinmek için sonraki öğreticiye geçin.