Entity Framework - คำอธิบายประกอบข้อมูล
DataAnnotations ใช้เพื่อกำหนดค่าคลาสซึ่งจะเน้นการกำหนดค่าที่จำเป็นโดยทั่วไป นอกจากนี้ DataAnnotations ยังเข้าใจโดยแอปพลิเคชัน. NET จำนวนมากเช่น ASP.NET MVC ซึ่งช่วยให้แอปพลิเคชันเหล่านี้ใช้ประโยชน์จากคำอธิบายประกอบเดียวกันสำหรับการตรวจสอบความถูกต้องฝั่งไคลเอ็นต์ แอตทริบิวต์ DataAnnotation แทนที่อนุสัญญา CodeFirst เริ่มต้น
System.ComponentModel.DataAnnotations รวมแอตทริบิวต์ต่อไปนี้ที่ส่งผลต่อความเป็นโมฆะหรือขนาดของคอลัมน์
- Key
- Timestamp
- ConcurrencyCheck
- Required
- MinLength
- MaxLength
- StringLength
System.ComponentModel.DataAnnotations.Schema เนมสเปซประกอบด้วยแอ็ตทริบิวต์ต่อไปนี้ที่มีผลต่อสคีมาของฐานข้อมูล
- Table
- Column
- Index
- ForeignKey
- NotMapped
- InverseProperty
สำคัญ
Entity Framework อาศัยทุกเอนทิตีที่มีค่าคีย์ที่ใช้ในการติดตามเอนทิตี หนึ่งในอนุสัญญาที่ Code First ขึ้นอยู่กับว่ามันบอกเป็นนัยว่าคุณสมบัติใดเป็นกุญแจสำคัญในแต่ละคลาสของ Code First
Convention คือการมองหาคุณสมบัติชื่อ“ Id” หรือคุณสมบัติที่รวมชื่อคลาสและ“ Id” เช่น“ StudentId”
คุณสมบัติจะแมปกับคอลัมน์คีย์หลักในฐานข้อมูล
ชั้นเรียนนักเรียนหลักสูตรและการลงทะเบียนเป็นไปตามอนุสัญญานี้
ตอนนี้สมมติว่าคลาสนักเรียนใช้ชื่อ StdntID แทน ID เมื่อ Code First ไม่พบคุณสมบัติที่ตรงกับข้อตกลงนี้จะทำให้เกิดข้อยกเว้นเนื่องจากข้อกำหนดของ Entity Framework ที่คุณต้องมีคุณสมบัติหลัก คุณสามารถใช้คำอธิบายประกอบคีย์เพื่อระบุคุณสมบัติที่จะใช้เป็น EntityKey
ลองมาดูรหัสต่อไปนี้ของชั้นเรียนนักเรียนซึ่งมี StdntID แต่ไม่เป็นไปตามหลักการเริ่มต้นของ Code First เพื่อจัดการกับสิ่งนี้จึงมีการเพิ่มแอตทริบิวต์คีย์ซึ่งจะทำให้เป็นคีย์หลัก
public class Student {
[Key]
public int StdntID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
เมื่อคุณเรียกใช้แอปพลิเคชันของคุณและตรวจสอบฐานข้อมูลของคุณใน SQL Server Explorer คุณจะเห็นว่าขณะนี้คีย์หลักคือ StdntID ในตารางนักเรียน
Entity Framework ยังรองรับคีย์คอมโพสิต Composite keysยังเป็นคีย์หลักที่ประกอบด้วยคุณสมบัติมากกว่าหนึ่งรายการ ตัวอย่างเช่นคุณมีคลาส DrivingLicense ซึ่งมีคีย์หลักผสมระหว่าง LicenseNumber และ IssuingCountry
public class DrivingLicense {
[Key, Column(Order = 1)]
public int LicenseNumber { get; set; }
[Key, Column(Order = 2)]
public string IssuingCountry { get; set; }
public DateTime Issued { get; set; }
public DateTime Expires { get; set; }
}
เมื่อคุณมีคีย์คอมโพสิต Entity Framework ต้องการให้คุณกำหนดลำดับของคุณสมบัติคีย์ คุณสามารถทำได้โดยใช้คำอธิบายประกอบคอลัมน์เพื่อระบุคำสั่งซื้อ
การประทับเวลา
Code First จะปฏิบัติต่อคุณสมบัติ Timestamp เช่นเดียวกับคุณสมบัติ ConcurrencyCheck แต่จะทำให้แน่ใจด้วยว่าฟิลด์ฐานข้อมูลที่โค้ดสร้างขึ้นครั้งแรกนั้นไม่เป็นค่าว่าง
เป็นเรื่องปกติมากขึ้นที่จะใช้เขตข้อมูล rowversion หรือ timestamp สำหรับการตรวจสอบการทำงานพร้อมกัน
แทนที่จะใช้คำอธิบายประกอบ ConcurrencyCheck คุณสามารถใช้คำอธิบายประกอบ TimeStamp ที่เฉพาะเจาะจงมากขึ้นได้ตราบเท่าที่ชนิดของคุณสมบัติเป็นไบต์อาร์เรย์
คุณสามารถมีคุณสมบัติการประทับเวลาได้เพียงหนึ่งรายการในคลาสที่กำหนด
ลองดูตัวอย่างง่ายๆโดยการเพิ่มคุณสมบัติ TimeStamp ในคลาส Course -
public class Course {
public int CourseID { get; set; }
public string Title { get; set; }
public int Credits { get; set; }
[Timestamp]
public byte[] TStamp { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
ดังที่คุณเห็นในตัวอย่างข้างต้นแอตทริบิวต์การประทับเวลาถูกนำไปใช้กับคุณสมบัติ Byte [] ของคลาสหลักสูตร ดังนั้น Code First จะสร้างคอลัมน์การประทับเวลาTStamp
ในตารางหลักสูตร
การทำงานพร้อมกันตรวจสอบ
คำอธิบายประกอบ ConcurrencyCheck ช่วยให้คุณสามารถตั้งค่าสถานะคุณสมบัติอย่างน้อยหนึ่งรายการเพื่อใช้สำหรับการตรวจสอบพร้อมกันในฐานข้อมูลเมื่อผู้ใช้แก้ไขหรือลบเอนทิตี หากคุณเคยทำงานกับ EF Designer สิ่งนี้จะสอดคล้องกับการตั้งค่า ConcurrencyMode ของคุณสมบัติเป็นคงที่
ลองมาดูตัวอย่างง่ายๆของการทำงานของ ConcurrencyCheck โดยการเพิ่มเข้าไปในคุณสมบัติ Title ในคลาส Course
public class Course {
public int CourseID { get; set; }
[ConcurrencyCheck]
public string Title { get; set; }
public int Credits { get; set; }
[Timestamp, DataType("timestamp")]
public byte[] TimeStamp { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
ในชั้นเรียนหลักสูตรข้างต้นแอตทริบิวต์ ConcurrencyCheck ถูกนำไปใช้กับคุณสมบัติ Title ที่มีอยู่ ตอนนี้ Code First จะรวมคอลัมน์ Title ไว้ในคำสั่ง update เพื่อตรวจสอบการเกิดพร้อมกันในแง่ดีดังที่แสดงในโค้ดต่อไปนี้
exec sp_executesql N'UPDATE [dbo].[Courses]
SET [Title] = @0
WHERE (([CourseID] = @1) AND ([Title] = @2))
',N'@0 nvarchar(max) ,@1 int,@2 nvarchar(max) ',@0=N'Maths',@1=1,@2=N'Calculus'
go
คำอธิบายประกอบที่จำเป็น
คำอธิบายประกอบที่จำเป็นจะบอก EF ว่าจำเป็นต้องมีคุณสมบัติเฉพาะ มาดูคลาสนักเรียนต่อไปนี้ซึ่งไอดีที่ต้องการถูกเพิ่มเข้าไปในคุณสมบัติ FirstMidName แอตทริบิวต์ที่จำเป็นจะบังคับให้ EF ตรวจสอบให้แน่ใจว่าคุณสมบัตินั้นมีข้อมูลอยู่
public class Student {
[Key]
public int StdntID { get; set; }
[Required]
public string LastName { get; set; }
[Required]
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
ดังที่เห็นในตัวอย่างข้างต้นแอตทริบิวต์ที่จำเป็นถูกนำไปใช้กับ FirstMidName และ LastName ดังนั้น Code First จะสร้างคอลัมน์ NOT NULL FirstMidName และ LastName ในตาราง Students ดังที่แสดงในภาพต่อไปนี้
MaxLength
แอตทริบิวต์ MaxLength ช่วยให้คุณระบุการตรวจสอบคุณสมบัติเพิ่มเติม สามารถนำไปใช้กับคุณสมบัติประเภทสตริงหรืออาร์เรย์ของคลาสโดเมน EF Code First จะกำหนดขนาดของคอลัมน์ตามที่ระบุในแอตทริบิวต์ MaxLength
มาดูคลาสหลักสูตรต่อไปนี้ซึ่งใช้แอตทริบิวต์ MaxLength (24) กับคุณสมบัติ Title
public class Course {
public int CourseID { get; set; }
[ConcurrencyCheck]
[MaxLength(24)]
public string Title { get; set; }
public int Credits { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
เมื่อคุณเรียกใช้แอปพลิเคชันข้างต้น Code First จะสร้างชื่อคอลัมน์ nvarchar (24) ในตาราง CourseId ดังที่แสดงในภาพต่อไปนี้
เมื่อผู้ใช้ตั้งค่า Title ซึ่งมีอักขระมากกว่า 24 ตัว EF จะโยน EntityValidationError
MinLength
แอตทริบิวต์ MinLength ยังช่วยให้คุณสามารถระบุการตรวจสอบคุณสมบัติเพิ่มเติมได้เช่นเดียวกับที่คุณทำกับ MaxLength นอกจากนี้ยังสามารถใช้แอตทริบิวต์ MinLength กับแอตทริบิวต์ MaxLength ดังที่แสดงในรหัสต่อไปนี้
public class Course {
public int CourseID { get; set; }
[ConcurrencyCheck]
[MaxLength(24) , MinLength(5)]
public string Title { get; set; }
public int Credits { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
EF จะโยน EntityValidationError ถ้าคุณตั้งค่าคุณสมบัติ Title น้อยกว่าความยาวที่ระบุในแอตทริบิวต์ MinLength หรือมากกว่าความยาวที่ระบุในแอตทริบิวต์ MaxLength
StringLength
StringLength ยังช่วยให้คุณระบุการตรวจสอบคุณสมบัติเพิ่มเติมเช่น MaxLength ข้อแตกต่างเพียงอย่างเดียวคือแอตทริบิวต์ StringLength สามารถใช้ได้กับคุณสมบัติประเภทสตริงของคลาสโดเมนเท่านั้น
public class Course {
public int CourseID { get; set; }
[StringLength (24)]
public string Title { get; set; }
public int Credits { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
Entity Framework ยังตรวจสอบค่าของคุณสมบัติสำหรับแอตทริบิวต์ StringLength หากผู้ใช้ตั้งค่า Title ซึ่งมีอักขระมากกว่า 24 ตัว EF จะโยน EntityValidationError
ตาราง
หลักการเริ่มต้นของ Code First สร้างชื่อตารางที่คล้ายกับชื่อคลาส หากคุณปล่อยให้ Code First สร้างฐานข้อมูลและต้องการเปลี่ยนชื่อของตารางที่กำลังสร้าง จากนั้น -
คุณสามารถใช้ Code First กับฐานข้อมูลที่มีอยู่ แต่ไม่ใช่ทุกกรณีที่ชื่อของคลาสจะตรงกับชื่อของตารางในฐานข้อมูลของคุณ
แอตทริบิวต์ของตารางจะแทนที่แบบแผนเริ่มต้นนี้
EF Code First จะสร้างตารางที่มีชื่อที่ระบุในแอตทริบิวต์ Table สำหรับคลาสโดเมนที่กำหนด
ลองมาดูตัวอย่างต่อไปนี้ที่ชั้นเรียนมีชื่อว่า Student และตามแบบแผน Code First สันนิษฐานว่าสิ่งนี้จะจับคู่กับตารางที่ชื่อนักเรียน หากไม่เป็นเช่นนั้นคุณสามารถระบุชื่อของตารางด้วยแอตทริบิวต์ Table ดังที่แสดงในรหัสต่อไปนี้
[Table("StudentsInfo")]
public class Student {
[Key]
public int StdntID { get; set; }
[Required]
public string LastName { get; set; }
[Required]
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
ตอนนี้คุณจะเห็นว่าแอตทริบิวต์ Table ระบุตารางเป็น StudentsInfo เมื่อสร้างตารางขึ้นคุณจะเห็นชื่อตาราง StudentsInfo ดังแสดงในภาพต่อไปนี้
คุณไม่สามารถระบุชื่อตารางเท่านั้น แต่คุณยังสามารถระบุสคีมาสำหรับตารางโดยใช้แอตทริบิวต์ Table ดังที่แสดงในโค้ดต่อไปนี้
[Table("StudentsInfo", Schema = "Admin")]
public class Student {
[Key]
public int StdntID { get; set; }
[Required]
public string LastName { get; set; }
[Required]
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
คุณสามารถดูในตัวอย่างด้านบนตารางถูกระบุด้วยสคีมาของผู้ดูแลระบบ ตอนนี้ Code First จะสร้างตาราง StudentsInfo ใน Admin schema ดังที่แสดงในภาพต่อไปนี้
คอลัมน์
นอกจากนี้ยังเหมือนกับแอตทริบิวต์ Table แต่แอตทริบิวต์ Table จะแทนที่ลักษณะการทำงานของตารางในขณะที่แอตทริบิวต์ Column จะแทนที่ลักษณะการทำงานของคอลัมน์ หลักการเริ่มต้นของ Code First สร้างชื่อคอลัมน์ที่คล้ายกับชื่อคุณสมบัติ หากคุณปล่อยให้ Code First สร้างฐานข้อมูลและต้องการเปลี่ยนชื่อคอลัมน์ในตารางของคุณด้วย จากนั้น -
แอตทริบิวต์ของคอลัมน์จะแทนที่หลักการเริ่มต้น
EF Code First จะสร้างคอลัมน์ที่มีชื่อที่ระบุในแอตทริบิวต์คอลัมน์สำหรับคุณสมบัติที่กำหนด
ลองดูตัวอย่างต่อไปนี้ซึ่งคุณสมบัตินี้มีชื่อว่า FirstMidName และตามแบบแผน Code First สันนิษฐานว่าสิ่งนี้จะแมปกับคอลัมน์ชื่อ FirstMidName
หากไม่ใช่กรณีนี้คุณสามารถระบุชื่อของคอลัมน์ด้วยแอตทริบิวต์ Column ดังที่แสดงในรหัสต่อไปนี้
public class Student {
public int ID { get; set; }
public string LastName { get; set; }
[Column("FirstName")]
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
คุณจะเห็นว่าคอลัมน์แอตทริบิวต์ระบุคอลัมน์เป็น FirstName เมื่อสร้างตารางขึ้นคุณจะเห็นชื่อคอลัมน์ FirstName ดังแสดงในภาพต่อไปนี้
ดัชนี
แอตทริบิวต์ Index ถูกนำมาใช้ใน Entity Framework 6.1 หากคุณใช้เวอร์ชันก่อนหน้านี้ข้อมูลในส่วนนี้จะใช้ไม่ได้
คุณสามารถสร้างดัชนีในคอลัมน์อย่างน้อยหนึ่งคอลัมน์โดยใช้ IndexAttribute
การเพิ่มแอตทริบิวต์ให้กับคุณสมบัติอย่างน้อยหนึ่งอย่างจะทำให้ EF สร้างดัชนีที่สอดคล้องกันในฐานข้อมูลเมื่อสร้างฐานข้อมูล
ดัชนีทำให้การดึงข้อมูลเร็วขึ้นและมีประสิทธิภาพในกรณีส่วนใหญ่ อย่างไรก็ตามการใส่ตารางหรือมุมมองที่มีดัชนีมากเกินไปอาจส่งผลต่อประสิทธิภาพของการดำเนินการอื่น ๆ เช่นการแทรกหรือการอัปเดต
การจัดทำดัชนีเป็นคุณลักษณะใหม่ใน Entity Framework ที่คุณสามารถปรับปรุงประสิทธิภาพของแอปพลิเคชัน Code First ของคุณได้โดยลดเวลาที่ต้องใช้ในการสืบค้นข้อมูลจากฐานข้อมูล
คุณสามารถเพิ่มดัชนีลงในฐานข้อมูลของคุณโดยใช้แอตทริบิวต์ดัชนีและแทนที่ค่าเริ่มต้นที่ไม่ซ้ำกันและการตั้งค่าคลัสเตอร์เพื่อให้ได้ดัชนีที่เหมาะสมที่สุดกับสถานการณ์ของคุณ
ตามค่าเริ่มต้นดัชนีจะถูกตั้งชื่อว่า IX_ <ชื่อคุณสมบัติ>
มาดูโค้ดต่อไปนี้ซึ่งมีการเพิ่มแอตทริบิวต์ดัชนีในคลาสหลักสูตรสำหรับเครดิต
public class Course {
public int CourseID { get; set; }
public string Title { get; set; }
[Index]
public int Credits { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
คุณจะเห็นว่าแอตทริบิวต์ดัชนีถูกนำไปใช้กับคุณสมบัติเครดิต เมื่อสร้างตารางขึ้นคุณจะเห็น IX_Credits ใน Indexes
โดยค่าเริ่มต้นดัชนีจะไม่ซ้ำกัน แต่คุณสามารถใช้ไฟล์ IsUniqueตั้งชื่อพารามิเตอร์เพื่อระบุว่าดัชนีควรไม่ซ้ำกัน ตัวอย่างต่อไปนี้แนะนำดัชนีเฉพาะดังที่แสดงในรหัสต่อไปนี้
public class Course {
public int CourseID { get; set; }
[Index(IsUnique = true)]
public string Title { get; set; }
[Index]
public int Credits { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
ForeignKey
การประชุม Code First จะดูแลความสัมพันธ์ที่พบบ่อยที่สุดในโมเดลของคุณ แต่มีบางกรณีที่ต้องการความช่วยเหลือ ตัวอย่างเช่นการเปลี่ยนชื่อของคุณสมบัติหลักในคลาสนักเรียนทำให้เกิดปัญหากับความสัมพันธ์กับคลาสการลงทะเบียน
public class Enrollment {
public int EnrollmentID { get; set; }
public int CourseID { get; set; }
public int StudentID { get; set; }
public Grade? Grade { get; set; }
public virtual Course Course { get; set; }
public virtual Student Student { get; set; }
}
public class Student {
[Key]
public int StdntID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
ในขณะที่สร้างฐานข้อมูล Code First จะเห็นคุณสมบัติ StudentID ในคลาสการลงทะเบียนและรับรู้โดยแบบแผนว่าตรงกับชื่อคลาสบวก“ ID” เป็นคีย์ต่างประเทศของคลาส Student อย่างไรก็ตามไม่มีคุณสมบัติ StudentID ในคลาส Student แต่คุณสมบัติ StdntID คือคลาส Student
วิธีแก้ปัญหานี้คือการสร้างคุณสมบัติการนำทางในการลงทะเบียนและใช้ ForeignKey DataAnnotation เพื่อช่วยให้ Code First เข้าใจวิธีสร้างความสัมพันธ์ระหว่างสองคลาสดังที่แสดงในโค้ดต่อไปนี้
public class Enrollment {
public int EnrollmentID { get; set; }
public int CourseID { get; set; }
public int StudentID { get; set; }
public Grade? Grade { get; set; }
public virtual Course Course { get; set; }
[ForeignKey("StudentID")]
public virtual Student Student { get; set; }
}
ตอนนี้คุณสามารถเห็นได้ว่าแอตทริบิวต์ ForeignKey ถูกนำไปใช้กับคุณสมบัติการนำทาง
ไม่แมป
ตามมาตรฐานเริ่มต้นของ Code First ทุกคุณสมบัติที่เป็นประเภทข้อมูลที่รองรับและซึ่งรวมถึง getters และ setters จะแสดงในฐานข้อมูล แต่นี่ไม่ใช่กรณีเสมอไปในแอปพลิเคชันของคุณ แอตทริบิวต์ NotMapped แทนที่แบบแผนเริ่มต้นนี้ ตัวอย่างเช่นคุณอาจมีคุณสมบัติในชั้นเรียนนักเรียนเช่น FatherName แต่ไม่จำเป็นต้องจัดเก็บ คุณสามารถใช้แอตทริบิวต์ NotMapped กับคุณสมบัติ FatherName ซึ่งคุณไม่ต้องการสร้างคอลัมน์ในฐานข้อมูลดังที่แสดงในรหัสต่อไปนี้
public class Student {
[Key]
public int StdntID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
[NotMapped]
public int FatherName { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
คุณจะเห็นว่ามีการใช้แอตทริบิวต์ NotMapped กับคุณสมบัติ FatherName เมื่อสร้างตารางคุณจะเห็นว่าคอลัมน์ FatherName จะไม่ถูกสร้างขึ้นในฐานข้อมูล แต่มีอยู่ในชั้นเรียนของนักเรียน
Code First จะไม่สร้างคอลัมน์สำหรับคุณสมบัติซึ่งไม่มี getters หรือ setters ดังที่แสดงในตัวอย่างคุณสมบัติ Address and Age ของคลาส Student ต่อไปนี้
คุณสมบัติผกผัน
InverseProperty ถูกใช้เมื่อคุณมีหลายความสัมพันธ์ระหว่างคลาส ในชั้นเรียนการลงทะเบียนคุณอาจต้องการติดตามผู้ที่ลงทะเบียนหลักสูตรปัจจุบันและหลักสูตรก่อนหน้า เพิ่มคุณสมบัติการนำทางสองรายการสำหรับคลาสการลงทะเบียน
public class Enrollment {
public int EnrollmentID { get; set; }
public int CourseID { get; set; }
public int StudentID { get; set; }
public Grade? Grade { get; set; }
public virtual Course CurrCourse { get; set; }
public virtual Course PrevCourse { get; set; }
public virtual Student Student { get; set; }
}
ในทำนองเดียวกันคุณจะต้องเพิ่มในชั้นเรียนหลักสูตรที่อ้างอิงโดยคุณสมบัติเหล่านี้ คลาสหลักสูตรมีคุณสมบัติการนำทางกลับไปที่คลาสการลงทะเบียนซึ่งมีการลงทะเบียนปัจจุบันและก่อนหน้าทั้งหมด
public class Course {
public int CourseID { get; set; }
public string Title { get; set; }
[Index]
public int Credits { get; set; }
public virtual ICollection<Enrollment> CurrEnrollments { get; set; }
public virtual ICollection<Enrollment> PrevEnrollments { get; set; }
}
Code First สร้างคอลัมน์คีย์ต่างประเทศของ {Class Name} _ {Primary Key} ถ้าคุณสมบัติ Foreign Key ไม่รวมอยู่ในคลาสเฉพาะดังที่แสดงในคลาสด้านบน เมื่อสร้างฐานข้อมูลคุณจะเห็นคีย์ต่างประเทศต่อไปนี้
อย่างที่คุณเห็นว่า Code first ไม่สามารถจับคู่คุณสมบัติในสองคลาสได้ด้วยตัวเอง ตารางฐานข้อมูลสำหรับการลงทะเบียนควรมีคีย์ต่างประเทศหนึ่งคีย์สำหรับ CurrCourse และอีกหนึ่งคีย์สำหรับ PrevCourse แต่ Code First จะสร้างคุณสมบัติคีย์ต่างประเทศสี่รายการ ได้แก่
- CurrCourse _CourseID
- PrevCourse _CourseID
- Course_CourseID และ
- Course_CourseID1
ในการแก้ไขปัญหาเหล่านี้คุณสามารถใช้คำอธิบายประกอบ InverseProperty เพื่อระบุการจัดตำแหน่งของคุณสมบัติ
public class Course {
public int CourseID { get; set; }
public string Title { get; set; }
[Index]
public int Credits { get; set; }
[InverseProperty("CurrCourse")]
public virtual ICollection<Enrollment> CurrEnrollments { get; set; }
[InverseProperty("PrevCourse")]
public virtual ICollection<Enrollment> PrevEnrollments { get; set; }
}
ดังที่คุณเห็นแอตทริบิวต์ InverseProperty ถูกนำไปใช้ในคลาสหลักสูตรข้างต้นโดยระบุคุณสมบัติอ้างอิงของคลาสการลงทะเบียนที่เป็นของ ตอนนี้ Code First จะสร้างฐานข้อมูลและสร้างคอลัมน์คีย์ต่างประเทศเพียงสองคอลัมน์ในตารางการลงทะเบียนดังที่แสดงในภาพต่อไปนี้
เราขอแนะนำให้คุณดำเนินการตามตัวอย่างข้างต้นในลักษณะทีละขั้นตอนเพื่อความเข้าใจที่ดีขึ้น