ASP.NET MVC Uygulaması için Daha Karmaşık Veri Modeli Oluşturma (4/10)
tarafından Tom Dykstra
Contoso University örnek web uygulaması, Entity Framework 5 Code First ve Visual Studio 2012 kullanarak ASP.NET MVC 4 uygulamalarının nasıl oluşturulacağını gösterir. Öğretici serisi hakkında bilgi için serideki ilk öğreticiye bakın.
Not
Çözemediğiniz bir sorunla karşılaşırsanız tamamlanmış bölümü indirin ve sorununuzu yeniden oluşturmayı deneyin. Kodunuzu tamamlanmış kodla karşılaştırarak genellikle sorunun çözümünü bulabilirsiniz. Bazı yaygın hatalar ve bunların nasıl çözüldüğü için bkz . Hatalar ve Geçici Çözümler.
Ö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. Veri modelini özelleştirmenin iki yolunu görürsünüz: varlık sınıflarına öznitelikler ekleyerek ve veritabanı bağlam sınıfına kod ekleyerek.
İşiniz bittiğinde varlık sınıfları, aşağıdaki çizimde gösterilen tamamlanmış veri modelini oluşturur:
Öznitelikleri Kullanarak 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ümlerden birkaçında, oluşturduğunuz sınıflara öznitelikler ekleyerek ve modeldeki kalan varlık türleri için yeni sınıflar oluşturarak tam School
veri modelini oluşturacaksınız.
DataType Özniteliği
Öğrenci kayıt tarihleri için, tüm web sayfaları şu anda tarihle birlikte saati de görüntüler, ancak bu alan için önemsediğiniz tek şey 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ılacağını gösteren bir örnek görmek için sınıfındaki Student
özelliğine EnrollmentDate
bir öznitelik ekleyeceksiniz.
Models\Student.cs içinde, ad alanı için System.ComponentModel.DataAnnotations
bir using
deyim ekleyin ve aşağıdaki örnekte gösterildiği gibi ö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 StudentID { 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 virtual 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. DataType NumaralandırmasıDate, Time, PhoneNumber, Currency, 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 tanıyabilir. Örneğin, DataType.EmailAddress için bir mailto:
bağlantı oluşturulabilir ve HTML5'i destekleyen tarayıcılarda DataType.Date için bir tarih seçici sağlanabilir. DataType öznitelikleri, HTML 5 tarayıcılarının anlayabileceği HTML 5 veri- (belirgin veri tiresi) öznitelikleri yayar. DataType öznitelikleri 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)]
public DateTime EnrollmentDate { get; set; }
ayar, ApplyFormatInEditMode
belirtilen biçimlendirmenin, değer düzenleme için bir metin kutusunda görüntülendiğinde 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.)
DisplayFormat özniteliğini tek başına kullanabilirsiniz, ancak DataType özniteliğini de kullanmak genellikle iyi bir fikirdir. DataType
özniteliği, verilerin ekranda nasıl işlendiğinin aksine semantiğini iletir ve ile DisplayFormat
elde 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ı vb.)
- Varsayılan olarak, tarayıcı yerel ayarınıza göre doğru biçimi kullanarak verileri işler.
- DataType özniteliği, MVC'nin verileri işlemek için doğru alan şablonunu seçmesini sağlayabilir (tek başına kullanılırsa DisplayFormat dize şablonunu kullanır). Daha fazla bilgi için bkz. Brad Wilson'ın ASP.NET MVC 2 Şablonları. (MVC 2 için yazılmış olsa da, bu makale ASP.NET MVC'nin geçerli sürümü için hala geçerlidir.)
özniteliğini DataType
bir tarih alanıyla kullanırsanız, alanın Chrome tarayıcılarında doğru şekilde işlenmesini sağlamak için özniteliğini de belirtmeniz DisplayFormat
gerekir. Daha fazla bilgi için bu StackOverflow iş parçacığına bakın.
Öğrenci Dizini sayfasını yeniden çalıştırın ve kayıt tarihleri için artık saatlerin görüntülenmediğini fark edin. Modeli kullanan Student
tüm görünümler için de aynı durum geçerli olacaktır.
The StringLengthAttribute
Öznitelikleri kullanarak veri doğrulama kuralları ve iletileri de belirtebilirsiniz. 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çin, aşağıdaki örnekte gösterildiği gibi ve FirstMidName
özelliklerine LastName
StringLength özniteliklerini ekleyin:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace ContosoUniversity.Models
{
public class Student
{
public int StudentID { get; set; }
[StringLength(50)]
public string LastName { get; set; }
[StringLength(50, ErrorMessage = "First name cannot be longer than 50 characters.")]
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime EnrollmentDate { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
}
StringLength özniteliği, kullanıcının bir ad için boşluk girmesini engellemez. Girişe kısıtlamalar uygulamak için RegularExpression özniteliğini kullanabilirsiniz. Örneğin, aşağıdaki kod ilk karakterin büyük harf, kalan karakterlerin ise alfabetik olmasını gerektirir:
[RegularExpression(@"^[A-Z]+[a-zA-Z""'\s-]*$")]
MaxLength özniteliği StringLength özniteliğine benzer işlevsellik sağlar ancak istemci tarafı doğrulaması sağlamaz.
Uygulamayı çalıştırın ve Öğrenciler sekmesine tıklayın. Aşağıdaki hatayı alırsınız:
Veritabanı oluşturulduktan sonra 'SchoolContext' bağlamını arka planlayan model değişti. Veritabanını (https://go.microsoft.com/fwlink/?LinkId=238269 güncelleştirmek için Code First Migrations kullanmayı göz önünde bulundurun.
Veritabanı modeli, veritabanı şemasında değişiklik gerektirecek şekilde değişmiştir ve Entity Framework bunu algılamıştır. Kullanıcı arabirimini kullanarak veritabanına eklediğiniz verileri kaybetmeden şemayı güncelleştirmek için geçişleri kullanacaksınız. yöntemi tarafından oluşturulan verileri değiştirdiyseniz, yönteminde Seed
Seed
kullandığınız AddOrUpdate yöntemi nedeniyle bu işlem özgün durumuna geri döndürülecektir. (AddOrUpdate , veritabanı terminolojisinden "upsert" işlemiyle eşdeğerdir.)
Paket Yöneticisi Konsolu'nda (PMC) aşağıdaki komutları girin:
add-migration MaxLengthOnNames
update-database
komutu timeStamp>_MaxLengthOnNames.cs adlı< bir dosya oluşturur.add-migration MaxLengthOnNames
Bu dosya, veritabanını geçerli veri modeliyle eşleşecek şekilde güncelleştirecek kodu içerir. Geçişler dosya adına eklenen zaman damgası, Entity Framework tarafından geçişleri sıralamak için kullanılır. Birden çok geçiş oluşturduktan sonra, veritabanını bırakırsanız veya Projeyi Geçişler'i kullanarak dağıtırsanız, tüm geçişler oluşturuldukları sırayla uygulanır.
Oluştur sayfasını çalıştırın ve 50 karakterden uzun bir ad girin. 50 karakteri aştığınızda istemci tarafı doğrulaması hemen bir hata iletisi gösterir.
Sütun Ö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 bu 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ı FirstName
istiyorsunuz. Bu eşlemeyi yapmak için özniteliğini Column
kullanabilirsiniz.
Column
özniteliği, veritabanı oluşturulduğunda, özelliğine eşleyen tablonun sütununun Student
FirstMidName
olarak adlandırılacağını FirstName
belirtir. Başka bir deyişle, kodunuz öğesine başvurduğunda Student.FirstMidName
veriler tablonun sütunundan FirstName
Student
gelir veya güncelleştirilir. Sütun adlarını belirtmezseniz, bunlara özellik adıyla aynı ad verilir.
Aşağıdaki vurgulanan kodda gösterildiği gibi, özelliğine System.ComponentModel.DataAnnotations.Schema için bir using deyimi ve sütun adı özniteliği ekleyin:FirstMidName
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace ContosoUniversity.Models
{
public class Student
{
public int StudentID { get; set; }
[StringLength(50)]
public string LastName { get; set; }
[StringLength(50, ErrorMessage = "First name cannot be longer than 50 characters.")]
[Column("FirstName")]
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime EnrollmentDate { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
}
Column özniteliğinin eklenmesi SchoolContext'i yedekleyerek modeli değiştirir, bu nedenle veritabanıyla eşleşmez. Başka bir geçiş oluşturmak için PMC'ye aşağıdaki komutları girin:
add-migration ColumnFirstName
update-database
Sunucu Gezgini'nde (Web için Express kullanıyorsanız Veritabanı Gezgini), Öğrenci tablosuna çift tıklayın.
Aşağıdaki görüntüde, ilk iki geçişi uygulamadan önceki özgün sütun adı gösterilmektedir. olarak değişen FirstMidName
FirstName
sütun adının yanı sıra, iki ad sütunu da uzunluğundan MAX
50 karaktere değiştirildi.
Bu öğreticinin ilerleyen bölümlerinde göreceğiniz gibi Fluent API'sini kullanarak veritabanı eşleme değişiklikleri de yapabilirsiniz.
Not
Bu varlık sınıflarının tümünü oluşturmadan önce derlemeyi denerseniz, derleyici hataları alabilirsiniz.
Eğitmen Varlığı Oluşturma
Models\Instructor.cs dosyasını oluşturup şablon kodunu aşağıdaki kodla değiştirin:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace ContosoUniversity.Models
{
public class Instructor
{
public int InstructorID { 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; }
public string FullName
{
get { return LastName + ", " + FirstMidName; }
}
public virtual ICollection<Course> Courses { get; set; }
public virtual OfficeAssignment OfficeAssignment { get; set; }
}
}
ve Instructor
varlıklarında birkaç özelliğin Student
aynı olduğuna dikkat edin. Bu serinin devamında yer alan Devralmayı Uygulama öğreticisinde, bu yedekliliği ortadan kaldırmak için devralmayı kullanarak yeniden düzenleyeceksiniz.
Gerekli ve Görüntüleme Öznitelikleri
özelliğindeki LastName
öznitelikler bunun gerekli bir alan olduğunu, metin kutusu için başlık "Soyadı" (alan olmadan "Soyadı" olacak özellik adı yerine) olması gerektiğini ve değerin 50 karakterden uzun olmayacağını belirtir.
[Required]
[Display(Name="Last Name")]
[StringLength(50)]
public string LastName { get; set; }
StringLength özniteliği veritabanındaki uzunluk üst sınırını ayarlar ve ASP.NET MVC için istemci tarafı ve sunucu tarafı doğrulaması sağlar. Bu öznitelikte en düşük dize uzunluğunu da belirtebilirsiniz, ancak minimum değerin veritabanı şeması üzerinde hiçbir etkisi yoktur. DateTime, int, double ve float gibi değer türleri için Required özniteliği gerekli değildir. Değer türlerine null değer atanamaz, bu nedenle doğal olarak gereklidirler. Required özniteliğini kaldırabilir ve özniteliği için StringLength
en düşük uzunluk parametresiyle değiştirebilirsiniz:
[Display(Name = "Last Name")]
[StringLength(50, MinimumLength=1)]
public string LastName { get; set; }
Bir satıra birden çok öznitelik koyabilirsiniz, böylece eğitmen sınıfını aşağıdaki gibi de yazabilirsiniz:
public class Instructor
{
public int InstructorID { get; set; }
[Display(Name = "Last Name"),StringLength(50, MinimumLength=1)]
public string LastName { get; set; }
[Column("FirstName"),Display(Name = "First Name"),StringLength(50, MinimumLength=1)]
public string FirstMidName { get; set; }
[DataType(DataType.Date),Display(Name = "Hire Date"),DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime HireDate { get; set; }
public string FullName
{
get { return LastName + ", " + FirstMidName; }
}
public virtual ICollection<Course> Courses { get; set; }
public virtual OfficeAssignment OfficeAssignment { get; set; }
}
FullName Hesaplanan Özelliği
FullName
, diğer iki özelliği birleştirerek oluşturulan bir değer döndüren hesaplanan özelliktir. Bu nedenle yalnızca bir get
erişimciye sahiptir ve veritabanında hiçbir FullName
sütun oluşturulmaz.
public string FullName
{
get { return LastName + ", " + FirstMidName; }
}
Kurslar ve OfficeAssignment Gezinti Özellikleri
Courses
ve OfficeAssignment
özellikleri gezinti özellikleridir. Daha önce açıklandığı gibi, yavaş yükleme adı verilen bir Entity Framework özelliğinden yararlanabilmeleri için genellikle sanal olarak tanımlanırlar. Ayrıca, bir gezinti özelliği birden çok varlığı barındırabiliyorsa, türünün ICollection<T> Arabirimini uygulaması gerekir. (Örneğin, IList<T>, Ekle'yi uygulamadığından IEnumerable<T'yi>IEnumerable<T>
niteler ancak nitelemez.
Eğitmen herhangi bir sayıda ders verebilir, bu nedenle Courses
varlık koleksiyonu Course
olarak tanımlanır. İş kurallarımız bir eğitmenin en fazla bir ofise sahip olabileceğini belirtir, bu nedenle OfficeAssignment
tek OfficeAssignment
bir varlık (herhangi bir ofis atanmamış olabilir null
) olarak tanımlanır.
public virtual ICollection<Course> Courses { get; set; }
public virtual OfficeAssignment OfficeAssignment { get; set; }
OfficeAssignment Varlığını oluşturma
Models \OfficeAssignment.cs dosyasını aşağıdaki kodla oluşturun:
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace ContosoUniversity.Models
{
public class OfficeAssignment
{
[Key]
[ForeignKey("Instructor")]
public int InstructorID { get; set; }
[StringLength(50)]
[Display(Name = "Office Location")]
public string Location { get; set; }
public virtual Instructor Instructor { get; set; }
}
}
Değişikliklerinizi kaydeden ve derleyicinin yakalayabileceği kopyalama ve yapıştırma hataları oluşturmadığınız doğrulayan projeyi derleyin.
Anahtar Özniteliği
ve OfficeAssignment
varlıkları arasında Instructor
bire sıfır veya bir ilişkisi vardır. 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 Entity Framework, adı veya sınıf adıID
adlandırma kuralına uymadığından 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]
[ForeignKey("Instructor")]
public int InstructorID { get; set; }
Varlığın Key
kendi birincil anahtarı varsa ancak özelliğine veya ID
dışında classnameID
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.
ForeignKey Özniteliği
İki varlık arasında (ve gibi OfficeAssignment
Instructor
) bire sıfıra veya bire bir ilişki olduğunda, EF ilişkinin hangi sonunun sorumlu ve hangi ucun bağımlı olduğunu çözemez. Bire bir ilişkiler, her sınıfta diğer sınıfa bir başvuru gezinti özelliğine sahiptir. İlişkiyi oluşturmak için ForeignKey Özniteliği bağımlı sınıfa uygulanabilir. ForeignKey Özniteliğini atlarsanız, geçişi oluşturmaya çalıştığınızda aşağıdaki hatayı alırsınız:
'ContosoUniversity.Models.OfficeAssignment' ve 'ContosoUniversity.Models.Instructor' türleri arasındaki ilişkilendirmenin asıl sonu belirlenemiyor. Bu ilişkilendirmenin asıl ucu, ilişki akıcı API'si veya veri ek açıklamaları kullanılarak açıkça yapılandırılmalıdır.
Öğreticinin ilerleyen bölümlerinde akıcı API ile bu ilişkiyi yapılandırmayı göstereceğiz.
Eğitmen Gezinti Özelliği
Varlığın Instructor
null atanabilir OfficeAssignment
bir gezinti özelliği vardır (eğitmenin ofis ataması olmayabilir) ve varlığın OfficeAssignment
boş değer atanamaz Instructor
bir gezinti özelliği vardır (bir ofis ataması eğitmen olmadan varolmadığından) InstructorID
null atanamaz. Bir Instructor
varlığın ilgili OfficeAssignment
bir varlığı olduğunda, her varlığın gezinti özelliğinde diğerine bir başvurusu olur.
İlgili bir eğitmenin olması gerektiğini belirtmek için Eğitmen gezinti özelliğine bir [Required]
öznitelik koyabilirsiniz, ancak InstructorID yabancı anahtarı (bu tablonun da anahtarıdır) null atanamaz olduğundan bunu yapmanız gerekmez.
Kurs Varlığını Değiştirme
Models\Course.cs dosyasında, daha önce eklediğiniz kodu aşağıdaki kodla değiştirin:
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; }
[Display(Name = "Department")]
public int DepartmentID { get; set; }
public virtual Department Department { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
public virtual ICollection<Instructor> Instructors { get; set; }
}
}
Kurs varlığı, ilgili Department
varlığa işaret eden bir yabancı anahtar özelliğine DepartmentID
ve bir Department
gezinti ö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. Ancak veri modelinde yabancı anahtarın olması, güncelleştirmeleri daha basit ve daha verimli hale getirebilir. Örneğin, düzenlemek üzere bir kurs varlığını getirdiğinizde, Department
yüklemezseniz varlık null olur, bu nedenle kurs varlığını güncelleştirdiğinizde ö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
özelliğinde CourseID
None parametresine sahip DatabaseGenerated ö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 departman için Course
1000 serisi, başka bir bölüm için 2000 serisi gibi kullanıcı tarafından belirtilen bir kurs numarası kullanacaksınız.
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 atanır, bu nedenle yukarıda belirtilen nedenlerle bir
DepartmentID
yabancı anahtar ve gezintiDepartment
özelliği vardır.public int DepartmentID { get; set; } public virtual Department Department { get; set; }
Bir kursa kayıtlı herhangi bir sayıda öğrenci olabilir, bu nedenle
Enrollments
gezinti özelliği bir koleksiyondur:public virtual ICollection<Enrollment> Enrollments { get; set; }
Bir kurs birden çok eğitmen tarafından öğretilebilir, bu nedenle
Instructors
gezinti özelliği bir koleksiyondur:public virtual ICollection<Instructor> Instructors { get; set; }
Departman Varlığı Oluşturma
Aşağıdaki kodla Models\Department.cs dosyasını oluşturun:
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)]
public DateTime StartDate { get; set; }
[Display(Name = "Administrator")]
public int? InstructorID { get; set; }
public virtual Instructor Administrator { get; set; }
public virtual ICollection<Course> Courses { get; set; }
}
}
Sütun Özniteliği
Daha önce sütun adı eşlemesini değiştirmek için Column özniteliğini kullandınız. Varlığın Department
kodunda özniteliği SQL Column
veri türü eşlemesini değiştirmek için kullanılır, böylece sütun veritabanındaki SQL Server para türü kullanılarak tanımlanır:
[Column(TypeName="money")]
public decimal Budget { get; set; }
Varlık Çerçevesi genellikle özellik 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 özellik, varlığın
InstructorID
yabancı anahtarıInstructor
olarak eklenir ve özelliği null atanabilir olarak işaretlemek için tür gösteriminden sonraint
bir soru işareti eklenir. Gezinti özelliği adlandırılmıştırAdministrator
ancak birInstructor
varlığı barındırmaktadır:public int? InstructorID { get; set; } public virtual Instructor Administrator { get; set; }
Bir bölümün birçok kursu olabilir, bu nedenle bir
Courses
gezinti özelliği vardır:public virtual ICollection<Course> Courses { get; set; }
Not
Kural gereği, Entity Framework null atanamayan yabancı anahtarlar ve çoka çok ilişkiler için art arda silmeyi etkinleştirir. Bu durum döngüsel art arda silme kurallarıyla sonuçlanabilir ve bu da başlatıcı kodunuz çalıştırıldığında bir özel duruma neden olur. Örneğin, özelliği null atanabilir olarak tanımlamadıysanız
Department.InstructorID
başlatıcı çalıştırıldığında şu özel durum iletisini alırsınız: "Başvurusal ilişki, izin verilmeyen döngüsel başvuruyla sonuçlanır." İş kurallarınız null atanamaz özellik gerektiriyorsaInstructorID
, ilişkide art arda silmeyi devre dışı bırakmak için aşağıdaki akıcı API'yi kullanmanız gerekir:
modelBuilder.Entity().HasRequired(d => d.Administrator).WithMany().WillCascadeOnDelete(false);
Öğrenci Varlığını Değiştirme
Models\Student.cs dosyasında, 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 StudentID { get; set; }
[StringLength(50, MinimumLength = 1)]
public string LastName { get; set; }
[StringLength(50, MinimumLength = 1, ErrorMessage = "First name cannot be longer than 50 characters.")]
[Column("FirstName")]
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; }
public string FullName
{
get { return LastName + ", " + FirstMidName; }
}
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
}
Kayıt Varlığı
Models\Enrollment.cs içinde, daha önce eklediğiniz kodu aşağıdaki kodla değiştirin
using System.ComponentModel.DataAnnotations;
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 virtual Course Course { get; set; }
public virtual 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 virtual 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 virtual Student Student { get; set; }
Çoka Çok İlişkiler
ve varlıkları arasında Student
çoka çok ilişki vardır ve Enrollment
varlık, veritabanında yükü olan çoka çok birleştirme tablosu olarak işlev görür.Course
Bu, 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 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.)
Her ilişki çizgisinin bir ucunda 1, diğer ucunda bir yıldız (*) vardır ve bu da bire çok ilişkisini gösterir.
Enrollment
Tabloda not bilgileri yoksa, yalnızca ve iki yabancı anahtarı CourseID
StudentID
içermesi gerekir. Bu durumda, veritabanında yükü ( veya saf birleştirme tablosu) olmayan çoka çok birleştirme tablosuna karşılık gelir ve bunun için bir model sınıfı oluşturmanız gerekmez. Instructor
ve Course
varlıkları bu tür bir çoka çok ilişkisine sahiptir ve gördüğünüz gibi aralarında varlık sınıfı yoktur:
Ancak, aşağıdaki veritabanı diyagramında gösterildiği gibi veritabanında birleştirme tablosu gereklidir:
Entity Framework tabloyu otomatik olarak oluşturur CourseInstructor
ve ve gezinti özelliklerini okuyup güncelleştirerek dolaylı olarak okuyup güncelleştirirsiniz Instructor.Courses
Course.Instructors
.
İ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.
Çoka çok ilişki çizgilerinin (* ile *) ve bire çok ilişki çizgilerinin (1 - *) yanı sıra, burada ve OfficeAssignment
varlıkları arasındaki Instructor
bire sıfır veya bir ilişki çizgisini (1 - 0,.1) ve Eğitmen ile Departman varlıkları arasındaki sıfır veya bire çok ilişki çizgisini (0,.1 - *) görebilirsiniz.
Veritabanı Bağlamı'na Kod ekleyerek Veri Modelini Özelleştirme
Ardından sınıfına yeni varlıklar SchoolContext
ekleyecek ve akıcı API çağrılarını kullanarak eşlemenin bazılarını özelleştireceksiniz. (API genellikle bir dizi yöntem çağrısını tek bir deyimde dizeleyerek kullanıldığından "akıcıdır".)
Bu öğreticide akıcı API'yi yalnızca özniteliklerle gerçekleştiremezseniz veritabanı eşlemesi için kullanacaksınız. 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 fluent 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" tutmak 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 uygulama bu iki yaklaşımdan birini seçmek ve bunu mümkün olduğunca tutarlı bir şekilde kullanmaktır.
Yeni varlıkları veri modeline eklemek ve öznitelikleri kullanarak yapmadığınız veritabanı eşlemesini gerçekleştirmek için DAL\SchoolContext.cs içindeki kodu aşağıdaki kodla değiştirin:
using ContosoUniversity.Models;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
namespace ContosoUniversity.DAL
{
public class SchoolContext : DbContext
{
public DbSet<Course> Courses { get; set; }
public DbSet<Department> Departments { get; set; }
public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Instructor> Instructors { get; set; }
public DbSet<Student> Students { get; set; }
public DbSet<OfficeAssignment> OfficeAssignments { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Course>()
.HasMany(c => c.Instructors).WithMany(i => i.Courses)
.Map(t => t.MapLeftKey("CourseID")
.MapRightKey("InstructorID")
.ToTable("CourseInstructor"));
}
}
}
OnModelCreating yöntemindeki yeni deyim çoka çok birleştirme tablosunu yapılandırıyor:
ve
Course
varlıkları arasındakiInstructor
çoka çok ilişkisi için kod birleştirme tablosunun tablo ve sütun adlarını belirtir. Code First, çoka çok ilişkisini sizin için bu kod olmadan yapılandırabilir, ancak çağırmıyorsanız sütun içinInstructorID
gibiInstructorInstructorID
varsayılan adlar alırsınız.modelBuilder.Entity<Course>() .HasMany(c => c.Instructors).WithMany(i => i.Courses) .Map(t => t.MapLeftKey("CourseID") .MapRightKey("InstructorID") .ToTable("CourseInstructor"));
Aşağıdaki kod, ve OfficeAssignment
varlıkları arasındaki Instructor
ilişkiyi belirtmek için öznitelikler yerine akıcı API'yi nasıl kullanabileceğinize ilişkin bir örnek sağlar:
modelBuilder.Entity<Instructor>()
.HasOptional(p => p.OfficeAssignment).WithRequired(p => p.Instructor);
"Fluent API" deyimlerinin arka planda ne yaptığı hakkında bilgi için Fluent API blog gönderisine bakın.
Test Verileriyle Veritabanının Tohumunu Oluşturma
Oluşturduğunuz yeni varlıklar için dengeli veri sağlamak için Migrations\Configuration.cs dosyasındaki kodu aşağıdaki kodla değiştirin.
namespace ContosoUniversity.Migrations
{
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq;
using ContosoUniversity.Models;
using ContosoUniversity.DAL;
internal sealed class Configuration : DbMigrationsConfiguration<SchoolContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(SchoolContext context)
{
var students = new List<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") }
};
students.ForEach(s => context.Students.AddOrUpdate(p => p.LastName, s));
context.SaveChanges();
var instructors = new List<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") }
};
instructors.ForEach(s => context.Instructors.AddOrUpdate(p => p.LastName, s));
context.SaveChanges();
var departments = new List<Department>
{
new Department { Name = "English", Budget = 350000,
StartDate = DateTime.Parse("2007-09-01"),
InstructorID = instructors.Single( i => i.LastName == "Abercrombie").InstructorID },
new Department { Name = "Mathematics", Budget = 100000,
StartDate = DateTime.Parse("2007-09-01"),
InstructorID = instructors.Single( i => i.LastName == "Fakhouri").InstructorID },
new Department { Name = "Engineering", Budget = 350000,
StartDate = DateTime.Parse("2007-09-01"),
InstructorID = instructors.Single( i => i.LastName == "Harui").InstructorID },
new Department { Name = "Economics", Budget = 100000,
StartDate = DateTime.Parse("2007-09-01"),
InstructorID = instructors.Single( i => i.LastName == "Kapoor").InstructorID }
};
departments.ForEach(s => context.Departments.AddOrUpdate(p => p.Name, s));
context.SaveChanges();
var courses = new List<Course>
{
new Course {CourseID = 1050, Title = "Chemistry", Credits = 3,
DepartmentID = departments.Single( s => s.Name == "Engineering").DepartmentID,
Instructors = new List<Instructor>()
},
new Course {CourseID = 4022, Title = "Microeconomics", Credits = 3,
DepartmentID = departments.Single( s => s.Name == "Economics").DepartmentID,
Instructors = new List<Instructor>()
},
new Course {CourseID = 4041, Title = "Macroeconomics", Credits = 3,
DepartmentID = departments.Single( s => s.Name == "Economics").DepartmentID,
Instructors = new List<Instructor>()
},
new Course {CourseID = 1045, Title = "Calculus", Credits = 4,
DepartmentID = departments.Single( s => s.Name == "Mathematics").DepartmentID,
Instructors = new List<Instructor>()
},
new Course {CourseID = 3141, Title = "Trigonometry", Credits = 4,
DepartmentID = departments.Single( s => s.Name == "Mathematics").DepartmentID,
Instructors = new List<Instructor>()
},
new Course {CourseID = 2021, Title = "Composition", Credits = 3,
DepartmentID = departments.Single( s => s.Name == "English").DepartmentID,
Instructors = new List<Instructor>()
},
new Course {CourseID = 2042, Title = "Literature", Credits = 4,
DepartmentID = departments.Single( s => s.Name == "English").DepartmentID,
Instructors = new List<Instructor>()
},
};
courses.ForEach(s => context.Courses.AddOrUpdate(p => p.CourseID, s));
context.SaveChanges();
var officeAssignments = new List<OfficeAssignment>
{
new OfficeAssignment {
InstructorID = instructors.Single( i => i.LastName == "Fakhouri").InstructorID,
Location = "Smith 17" },
new OfficeAssignment {
InstructorID = instructors.Single( i => i.LastName == "Harui").InstructorID,
Location = "Gowan 27" },
new OfficeAssignment {
InstructorID = instructors.Single( i => i.LastName == "Kapoor").InstructorID,
Location = "Thompson 304" },
};
officeAssignments.ForEach(s => context.OfficeAssignments.AddOrUpdate(p => p.Location, s));
context.SaveChanges();
AddOrUpdateInstructor(context, "Chemistry", "Kapoor");
AddOrUpdateInstructor(context, "Chemistry", "Harui");
AddOrUpdateInstructor(context, "Microeconomics", "Zheng");
AddOrUpdateInstructor(context, "Macroeconomics", "Zheng");
AddOrUpdateInstructor(context, "Calculus", "Fakhouri");
AddOrUpdateInstructor(context, "Trigonometry", "Harui");
AddOrUpdateInstructor(context, "Composition", "Abercrombie");
AddOrUpdateInstructor(context, "Literature", "Abercrombie");
context.SaveChanges();
var enrollments = new List<Enrollment>
{
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alexander").StudentID,
CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID,
Grade = Grade.A
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alexander").StudentID,
CourseID = courses.Single(c => c.Title == "Microeconomics" ).CourseID,
Grade = Grade.C
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alexander").StudentID,
CourseID = courses.Single(c => c.Title == "Macroeconomics" ).CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alonso").StudentID,
CourseID = courses.Single(c => c.Title == "Calculus" ).CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alonso").StudentID,
CourseID = courses.Single(c => c.Title == "Trigonometry" ).CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alonso").StudentID,
CourseID = courses.Single(c => c.Title == "Composition" ).CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Anand").StudentID,
CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Anand").StudentID,
CourseID = courses.Single(c => c.Title == "Microeconomics").CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Barzdukas").StudentID,
CourseID = courses.Single(c => c.Title == "Chemistry").CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Li").StudentID,
CourseID = courses.Single(c => c.Title == "Composition").CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Justice").StudentID,
CourseID = courses.Single(c => c.Title == "Literature").CourseID,
Grade = Grade.B
}
};
foreach (Enrollment e in enrollments)
{
var enrollmentInDataBase = context.Enrollments.Where(
s =>
s.Student.StudentID == e.StudentID &&
s.Course.CourseID == e.CourseID).SingleOrDefault();
if (enrollmentInDataBase == null)
{
context.Enrollments.Add(e);
}
}
context.SaveChanges();
}
void AddOrUpdateInstructor(SchoolContext context, string courseTitle, string instructorName)
{
var crs = context.Courses.SingleOrDefault(c => c.Title == courseTitle);
var inst = crs.Instructors.SingleOrDefault(i => i.LastName == instructorName);
if (inst == null)
crs.Instructors.Add(context.Instructors.Single(i => i.LastName == instructorName));
}
}
}
İlk öğreticide gördüğünüz gibi, bu kodun çoğu yalnızca yeni varlık nesnelerini güncelleştirir veya oluşturur ve test için gereken örnek verileri özelliklere yükler. Ancak varlıkla çoka çok ilişkisi olan varlığın nasıl Course
işlendiğine Instructor
dikkat edin:
var courses = new List<Course>
{
new Course {CourseID = 1050, Title = "Chemistry", Credits = 3,
Department = departments.Single( s => s.Name == "Engineering"),
Instructors = new List<Instructor>()
},
...
};
courses.ForEach(s => context.Courses.AddOrUpdate(p => p.CourseID, s));
context.SaveChanges();
Bir Course
nesnesi oluşturduğunuzda, gezinti özelliğini kodunu Instructors = new List<Instructor>()
kullanarak boş bir koleksiyon olarak başlatırsınızInstructors
. Bu, yöntemi kullanılarak bununla Course
ilgili varlıkların eklenmesini Instructor
Instructors.Add
mümkün kılar. Boş liste oluşturmadıysanız bu ilişkileri ekleyemezsiniz çünkü Instructors
özelliği null olur ve bir Add
yöntemi olmaz. Liste başlatmayı oluşturucuya da ekleyebilirsiniz.
Geçiş Ekleme ve Veritabanını Güncelleştirme
PMC'den şu komutu girin add-migration
:
PM> add-Migration Chap4
Bu noktada veritabanını güncelleştirmeyi denerseniz 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" adlı "dbo" tablosunda oluştu. Department", "DepartmentID" sütunu.
<timestamp>_Chap4.cs dosyasını düzenleyin ve aşağıdaki kod değişikliklerini yapın (sql deyimi ekleyip deyimini AddColumn
değiştireceksiniz):
CreateTable(
"dbo.CourseInstructor",
c => new
{
CourseID = c.Int(nullable: false),
InstructorID = c.Int(nullable: false),
})
.PrimaryKey(t => new { t.CourseID, t.InstructorID })
.ForeignKey("dbo.Course", t => t.CourseID, cascadeDelete: true)
.ForeignKey("dbo.Instructor", t => t.InstructorID, cascadeDelete: true)
.Index(t => t.CourseID)
.Index(t => t.InstructorID);
// Create a department for course to point to.
Sql("INSERT INTO dbo.Department (Name, Budget, StartDate) VALUES ('Temp', 0.00, GETDATE())");
// default value for FK points to department created above.
AddColumn("dbo.Course", "DepartmentID", c => c.Int(nullable: false, defaultValue: 1));
//AddColumn("dbo.Course", "DepartmentID", c => c.Int(nullable: false));
AlterColumn("dbo.Course", "Title", c => c.String(maxLength: 50));
AddForeignKey("dbo.Course", "DepartmentID", "dbo.Department", "DepartmentID", cascadeDelete: true);
CreateIndex("dbo.Course", "DepartmentID");
}
public override void Down()
{
(Yeni satırı eklerken var olan AddColumn
satırı açıklama satırı yaptığınızdan veya sildiğinizden emin olun; aksi zaman komutu girdiğinizde update-database
hata alırsınız.)
Bazen geçişleri mevcut verilerle yürütürken, yabancı anahtar kısıtlamalarını karşılamak için veritabanına saplama verileri eklemeniz gerekir ve şu anda bunu yapıyorsunuz. Oluşturulan kod tabloya Course
null atanamaz DepartmentID
bir yabancı anahtar ekler. Kod çalıştırıldığında tabloda zaten satırlar Course
varsa, AddColumn
SQL Server sütuna null olmayan hangi değeri koyacağını bilmediğinden işlem başarısız olur. Bu nedenle kodu yeni sütuna varsayılan bir değer verecek şekilde değiştirdiniz ve varsayılan bölüm olarak görev yapmak için "Temp" adlı bir saplama departmanı oluşturdunuz. Sonuç olarak, bu kod çalıştırıldığında var olan Course
satırlar varsa, bunların tümü "Geçici" departmanıyla ilişkilendirilir.
Seed
Yöntem çalıştırıldığında tabloya Department
satır ekler ve var olan Course
satırları bu yeni Department
satırlarla ilişkilendirir. Kullanıcı arabirimine hiç kurs eklemediyseniz artık "Geçici" bölümüne veya sütundaki varsayılan değere Course.DepartmentID
ihtiyacınız kalmaz. Birinin uygulamayı kullanarak kurs eklemiş olma olasılığına izin vermek için, sütundan varsayılan değeri kaldırıp "Geçici" bölümünü silmeden önce tüm Course
satırların (yalnızca yöntemin önceki çalıştırmaları Seed
tarafından eklenenler değil) geçerli DepartmentID
değerlere sahip olduğundan emin olmak için yöntem kodunu da güncelleştirmek Seed
istersiniz.
Timestamp>_Chap4.cs dosyasını düzenlemeyi < bitirdikten sonra, geçişi yürütmek için PMC'ye komutunu girinupdate-database
.
Not
Verileri geçirirken ve şema değişiklikleri yaparken başka hatalar da alabilirsiniz. Çözemediğiniz geçiş hataları alırsanız, Web.config dosyasındaki bağlantı dizesini değiştirebilir veya veritabanını silebilirsiniz. En basit yaklaşım, veritabanınıWeb.config dosyasında yeniden adlandırmaktır. Örneğin, aşağıda gösterildiği gibi veritabanı adını CU_test olarak değiştirin:
<add name="SchoolContext" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=CU_Test;
Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\CU_Test.mdf"
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.
Daha önce yaptığınız gibi veritabanını Sunucu Gezgini'nde açın ve tüm tabloların oluşturulduğunu görmek için Tablolar düğümünü genişletin. ( Sunucu Gezgini daha önce açık durumdaysa Yenile düğmesine tıklayın.)
Tablo için CourseInstructor
model sınıfı oluşturmadınız. Daha önce açıklandığı gibi, bu ve Course
varlıkları arasındaki Instructor
çoka çok ilişkisine yönelik bir birleştirme tablosudur.
Tabloya CourseInstructor
sağ tıklayın ve gezinti özelliğine eklediğiniz varlıkların Instructor
bir sonucu olarak tabloya veri eklendiğini doğrulamak için Course.Instructors
Tablo Verilerini Göster'i seçin.
Özet
Artık daha karmaşık bir veri modeline ve buna karşılık gelen veritabanına sahipsiniz. Aşağıdaki öğreticide, ilgili verilere erişmenin farklı yolları hakkında daha fazla bilgi edineceksiniz.
Diğer Entity Framework kaynaklarına bağlantılar ASP.NET Veri Erişimi İçerik Eşlemesi'nde bulunabilir.
Geri Bildirim
https://aka.ms/ContentUserFeedback.
Çok yakında: 2024 boyunca, içerik için geri bildirim mekanizması olarak GitHub Sorunları’nı kullanımdan kaldıracak ve yeni bir geri bildirim sistemiyle değiştireceğiz. Daha fazla bilgi için bkz.Gönderin ve geri bildirimi görüntüleyin