Kerangka Kerja Entitas - Anotasi Data

DataAnnotations digunakan untuk mengonfigurasi kelas yang akan menyoroti konfigurasi yang paling sering dibutuhkan. DataAnnotations juga dipahami oleh sejumlah aplikasi .NET, seperti ASP.NET MVC yang memungkinkan aplikasi ini memanfaatkan anotasi yang sama untuk validasi sisi klien. Atribut DataAnnotation menggantikan konvensi CodeFirst default.

System.ComponentModel.DataAnnotations termasuk atribut berikut yang mempengaruhi nullability atau ukuran kolom.

  • Key
  • Timestamp
  • ConcurrencyCheck
  • Required
  • MinLength
  • MaxLength
  • StringLength

System.ComponentModel.DataAnnotations.Schema namespace menyertakan atribut berikut yang memengaruhi skema database.

  • Table
  • Column
  • Index
  • ForeignKey
  • NotMapped
  • InverseProperty

Kunci

Kerangka Kerja Entitas bergantung pada setiap entitas yang memiliki nilai kunci yang digunakannya untuk melacak entitas. Salah satu konvensi yang bergantung pada Code First adalah bagaimana ia menyiratkan properti mana yang merupakan kunci di setiap kelas Code First.

  • Konvensi mencari properti bernama "Id" atau salah satu yang menggabungkan nama kelas dan "Id", seperti "StudentId".

  • Properti akan dipetakan ke kolom kunci utama dalam database.

  • Kelas Pelajar, Kursus dan Pendaftaran mengikuti konvensi ini.

Sekarang anggaplah kelas Student menggunakan nama StdntID sebagai ganti ID. Ketika Code First tidak menemukan properti yang cocok dengan konvensi ini, itu akan memunculkan pengecualian karena persyaratan Entity Framework bahwa Anda harus memiliki properti kunci. Anda dapat menggunakan anotasi kunci untuk menentukan properti mana yang akan digunakan sebagai EntityKey.

Mari kita lihat kode kelas Student berikut yang berisi StdntID, tetapi tidak mengikuti konvensi Code First default. Jadi untuk menangani ini, atribut Key ditambahkan yang akan menjadikannya sebagai kunci utama.

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; }
}

Saat Anda menjalankan aplikasi dan melihat ke database Anda di SQL Server Explorer, Anda akan melihat bahwa kunci utama sekarang adalah StdntID di tabel Siswa.

Entity Framework juga mendukung kunci komposit. Composite keysjuga merupakan kunci utama yang terdiri dari lebih dari satu properti. Misalnya, Anda memiliki kelas DrivingLicense yang kunci utamanya adalah kombinasi dari LicenseNumber dan 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; }
}

Saat Anda memiliki kunci komposit, Entity Framework mengharuskan Anda untuk menentukan urutan properti kunci. Anda dapat melakukan ini menggunakan anotasi Kolom untuk menentukan pesanan.

Stempel waktu

Code First akan memperlakukan properti Timestamp sama seperti properti ConcurrencyCheck, tetapi juga akan memastikan bahwa bidang database yang pertama kali dibuat kode adalah non-nullable.

  • Lebih umum menggunakan kolom rowversion atau timestamp untuk pemeriksaan konkurensi.

  • Daripada menggunakan anotasi ConcurrencyCheck, Anda dapat menggunakan anotasi TimeStamp yang lebih spesifik selama jenis propertinya adalah byte array.

  • Anda hanya dapat memiliki satu properti stempel waktu di kelas tertentu.

Mari kita lihat contoh sederhana dengan menambahkan properti TimeStamp ke kelas 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; }
}

Seperti yang Anda lihat pada contoh di atas, atribut Timestamp diterapkan ke properti Byte [] kelas Kursus. Jadi, Code First akan membuat kolom timestamp TStampdi tabel Kursus.

ConcurrencyCheck

Anotasi ConcurrencyCheck memungkinkan Anda menandai satu atau beberapa properti yang akan digunakan untuk pemeriksaan konkurensi dalam database saat pengguna mengedit atau menghapus entitas. Jika Anda telah bekerja dengan EF Designer, ini sejalan dengan pengaturan ConcurrencyMode properti ke Tetap.

Mari kita lihat contoh sederhana bagaimana ConcurrencyCheck bekerja dengan menambahkannya ke properti Title di kelas 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; }
}

Di kelas Kursus di atas, atribut ConcurrencyCheck diterapkan ke properti Judul yang ada. Sekarang, Kode Pertama akan menyertakan kolom Judul dalam perintah pembaruan untuk memeriksa konkurensi optimis seperti yang ditunjukkan pada kode berikut.

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

Anotasi yang Diperlukan

Anotasi Wajib memberi tahu EF bahwa properti tertentu diperlukan. Mari kita lihat kelas Mahasiswa berikut di mana Id yang diperlukan ditambahkan ke properti FirstMidName. Atribut wajib akan memaksa EF untuk memastikan bahwa properti tersebut memiliki data di dalamnya.

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; }
}

Seperti yang terlihat pada contoh di atas, atribut Wajib diterapkan ke FirstMidName dan LastName. Jadi, Code First akan membuat kolom NOT NULL FirstMidName dan LastName di tabel Students seperti yang ditunjukkan pada gambar berikut.

Panjang maksimal

Atribut MaxLength memungkinkan Anda untuk menentukan validasi properti tambahan. Ini dapat diterapkan ke properti tipe string atau array dari kelas domain. EF Code First akan mengatur ukuran kolom seperti yang ditentukan dalam atribut MaxLength.

Mari kita lihat kelas Kursus berikut di mana atribut MaxLength (24) diterapkan ke properti Judul.

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; }
}

Ketika Anda menjalankan aplikasi di atas, Kode Pertama akan membuat Judul kolom nvarchar (24) di tabel CourseId seperti yang ditunjukkan pada gambar berikut.

Saat pengguna menyetel Judul yang berisi lebih dari 24 karakter, EF akan menampilkan EntityValidationError.

MinLength

Atribut MinLength juga memungkinkan Anda untuk menentukan validasi properti tambahan, seperti yang Anda lakukan dengan MaxLength. Atribut MinLength juga dapat digunakan dengan atribut MaxLength seperti yang ditunjukkan pada kode berikut.

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 akan menampilkan EntityValidationError, jika Anda menetapkan nilai properti Judul kurang dari panjang yang ditentukan dalam atribut MinLength atau lebih besar dari panjang yang ditentukan dalam atribut MaxLength.

StringLength

StringLength juga memungkinkan Anda untuk menentukan validasi properti tambahan seperti MaxLength. Satu-satunya perbedaan adalah atribut StringLength hanya dapat diterapkan ke properti tipe string kelas Domain.

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 juga memvalidasi nilai properti untuk atribut StringLength. Jika pengguna menyetel Judul yang berisi lebih dari 24 karakter, EF akan menampilkan EntityValidationError.

Meja

Kode Default Konvensi pertama membuat nama tabel yang mirip dengan nama kelas. Jika Anda mengizinkan Code First membuat database, dan juga ingin mengubah nama tabel yang dibuatnya. Lalu -

  • Anda dapat menggunakan Code First dengan database yang sudah ada. Tetapi tidak selalu terjadi bahwa nama kelas cocok dengan nama tabel di database Anda.

  • Atribut tabel menggantikan konvensi default ini.

  • EF Code First akan membuat tabel dengan nama yang ditentukan dalam atribut Tabel untuk kelas domain tertentu.

Mari kita lihat contoh berikut di mana kelas bernama Student dan menurut konvensi, Code First menganggap ini akan dipetakan ke tabel bernama Students. Jika bukan itu masalahnya, Anda dapat menentukan nama tabel dengan atribut Tabel seperti yang ditunjukkan pada kode berikut.

[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; }
}

Sekarang Anda dapat melihat bahwa atribut Table menetapkan tabel sebagai StudentsInfo. Ketika tabel dibuat, Anda akan melihat nama tabel StudentsInfo seperti yang ditunjukkan pada gambar berikut.

Anda tidak hanya dapat menentukan nama tabel tetapi Anda juga dapat menentukan skema untuk tabel menggunakan atribut Tabel seperti yang ditunjukkan pada kode berikut.

[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; }
}

Anda dapat melihat pada contoh di atas, tabel ditentukan dengan skema admin. Sekarang Code First akan membuat tabel StudentsInfo di skema Admin seperti yang ditunjukkan pada gambar berikut.

Kolom

Ini juga sama dengan atribut Tabel, tetapi atribut Tabel menggantikan perilaku tabel sementara atribut Kolom menggantikan perilaku kolom. Kode Default Pertama, konvensi membuat nama kolom yang mirip dengan nama properti. Jika Anda mengizinkan Code First membuat database, dan juga ingin mengubah nama kolom di tabel Anda. Lalu -

  • Atribut kolom menggantikan konvensi default.

  • EF Code First akan membuat kolom dengan nama yang ditentukan di atribut Kolom untuk properti tertentu.

Mari kita lihat contoh berikut di mana properti bernama FirstMidName dan menurut konvensi, Code First menganggap ini akan dipetakan ke kolom bernama FirstMidName.

Jika tidak demikian, Anda dapat menentukan nama kolom dengan atribut Kolom seperti yang ditunjukkan pada kode berikut.

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; }
}

Anda dapat melihat bahwa atribut Column menentukan kolom sebagai FirstName. Ketika tabel dibuat, Anda akan melihat nama kolom FirstName seperti yang ditunjukkan pada gambar berikut.

Indeks

Atribut Indeks diperkenalkan di Entity Framework 6.1. Jika Anda menggunakan versi sebelumnya, informasi di bagian ini tidak berlaku.

  • Anda dapat membuat indeks pada satu atau lebih kolom menggunakan IndexAttribute.

  • Menambahkan atribut ke satu atau lebih properti akan menyebabkan EF membuat indeks yang sesuai dalam database saat membuat database.

  • Indeks membuat pengambilan data lebih cepat dan efisien, dalam banyak kasus. Namun, membebani tabel atau tampilan dengan indeks secara tidak menyenangkan dapat memengaruhi kinerja operasi lain seperti penyisipan atau pembaruan.

  • Pengindeksan adalah fitur baru dalam Entity Framework di mana Anda dapat meningkatkan kinerja aplikasi Code First Anda dengan mengurangi waktu yang diperlukan untuk membuat kueri data dari database.

  • Anda dapat menambahkan indeks ke database Anda menggunakan atribut Indeks, dan mengganti pengaturan Unik dan Berkelompok default untuk mendapatkan indeks yang paling sesuai dengan skenario Anda.

  • Secara default, indeks akan diberi nama IX_ <nama properti>

Mari kita lihat kode berikut di mana atribut Indeks ditambahkan di kelas Kursus untuk Kredit.

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; }
}

Anda dapat melihat bahwa atribut Index diterapkan ke properti Credits. Saat tabel dibuat, Anda akan melihat IX_Credits di Indeks.

Secara default, indeks tidak unik, tetapi Anda dapat menggunakan IsUniqueparameter bernama untuk menentukan bahwa indeks harus unik. Contoh berikut memperkenalkan indeks unik seperti yang ditunjukkan pada kode berikut.

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; }
}

Kunci asing

Konvensi Code First akan menangani hubungan paling umum dalam model Anda, tetapi ada beberapa kasus yang memerlukan bantuan. Misalnya, dengan mengubah nama properti kunci di kelas Siswa membuat masalah dengan hubungannya dengan kelas Pendaftaran.

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; }
}

Saat membuat database, Code First melihat properti StudentID di kelas Enrollment dan mengenalinya, dengan konvensi yang cocok dengan nama kelas ditambah "ID", sebagai kunci asing untuk kelas Student. Namun, tidak ada properti StudentID di kelas Student, tetapi properti StdntID adalah kelas Student.

Solusi untuk ini adalah dengan membuat properti navigasi di Pendaftaran dan menggunakan ForeignKey DataAnnotation untuk membantu Code First memahami cara membangun hubungan antara dua kelas seperti yang ditunjukkan pada kode berikut.

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; }
}

Anda sekarang dapat melihat bahwa atribut ForeignKey diterapkan ke properti navigasi.

NotMapped

Secara default, konvensi Code First, setiap properti yang memiliki tipe data yang didukung dan yang menyertakan getter dan setter direpresentasikan dalam database. Tetapi ini tidak selalu terjadi dalam aplikasi Anda. Atribut NotMapped menggantikan konvensi default ini. Misalnya, Anda mungkin memiliki properti di kelas Mahasiswa seperti NamaBapak, tetapi properti itu tidak perlu disimpan. Anda dapat menerapkan atribut NotMapped ke properti FatherName yang tidak ingin Anda buat kolomnya di database seperti yang ditunjukkan pada kode berikut.

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; }
}

Anda dapat melihat bahwa atribut NotMapped diterapkan ke properti FatherName. Ketika tabel dibuat, Anda akan melihat bahwa kolom NamaBapak tidak akan dibuat dalam database, tetapi ada di kelas Siswa.

Kode Pertama tidak akan membuat kolom untuk properti, yang tidak memiliki pengambil atau penyetel seperti yang diperlihatkan dalam contoh properti Alamat dan Usia kelas Siswa berikut.

InverseProperty

InverseProperty digunakan ketika Anda memiliki beberapa hubungan antar kelas. Di kelas Pendaftaran, Anda mungkin ingin melacak siapa yang mendaftar Kursus Saat Ini dan Kursus Sebelumnya. Mari tambahkan dua properti navigasi untuk kelas Pendaftaran.

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; }
}

Demikian pula, Anda juga perlu menambahkan kelas Kursus yang dirujuk oleh properti ini. Kelas Kursus memiliki properti navigasi kembali ke kelas Pendaftaran, yang berisi semua pendaftaran saat ini dan sebelumnya.

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 membuat kolom foreign key {Class Name} _ {Primary Key}, jika properti foreign key tidak termasuk dalam kelas tertentu seperti yang ditunjukkan pada kelas di atas. Saat database dibuat, Anda akan melihat kunci asing berikut.

Seperti yang Anda lihat, Kode pertama tidak dapat mencocokkan properti di dua kelas itu sendiri. Tabel database untuk Pendaftaran harus memiliki satu kunci asing untuk CurrCourse dan satu untuk PrevCourse, tetapi Kode Pertama akan membuat empat properti kunci asing, yaitu

  • CurrCourse _CourseID
  • PrevCourse _CourseID
  • Course_CourseID, dan
  • Course_CourseID1

Untuk memperbaiki masalah ini, Anda dapat menggunakan anotasi InverseProperty untuk menentukan penyelarasan properti.

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; }
}

Seperti yang Anda lihat, atribut InverseProperty diterapkan di kelas Kursus di atas dengan menentukan properti referensi kelas Pendaftaran yang mana. Sekarang, Code First akan menghasilkan database dan hanya membuat dua kolom kunci asing di tabel Pendaftaran seperti yang ditunjukkan pada gambar berikut.

Kami menyarankan Anda untuk menjalankan contoh di atas dengan cara langkah demi langkah untuk pemahaman yang lebih baik.