Bagikan melalui


Hubungan, properti navigasi, dan kunci asing

Artikel ini memberikan gambaran umum tentang bagaimana Kerangka Kerja Entitas mengelola hubungan antar entitas. Ini juga memberikan beberapa panduan tentang cara memetakan dan memanipulasi hubungan.

Hubungan dalam EF

Dalam database relasional, hubungan (juga disebut asosiasi) antara tabel didefinisikan melalui kunci asing. Kunci asing (FK) adalah kolom atau kombinasi kolom yang digunakan untuk membuat dan menerapkan tautan antara data dalam dua tabel. Umumnya ada tiga jenis hubungan: satu-ke-satu, satu-ke-banyak, dan banyak-ke-banyak. Dalam hubungan satu ke banyak, kunci asing didefinisikan pada tabel yang mewakili banyak akhir hubungan. Hubungan banyak ke banyak melibatkan penentuan tabel ketiga (disebut persimpangan atau tabel gabungan), yang kunci utamanya terdiri dari kunci asing dari kedua tabel terkait. Dalam hubungan satu-ke-satu, kunci utama bertindak juga sebagai kunci asing dan tidak ada kolom kunci asing terpisah untuk salah satu tabel.

Gambar berikut menunjukkan dua tabel yang berpartisipasi dalam hubungan satu ke banyak. Tabel Kursus adalah tabel dependen karena berisi kolom DepartmentID yang menautkannya ke tabel Departemen .

Department and Course tables

Dalam Kerangka Kerja Entitas, entitas dapat terkait dengan entitas lain melalui asosiasi atau hubungan. Setiap hubungan berisi dua ujung yang menjelaskan jenis entitas dan perkalian jenis (satu, nol atau satu, atau banyak) untuk dua entitas dalam hubungan tersebut. Hubungan dapat diatur oleh batasan referensial, yang menjelaskan mana yang berakhir dalam hubungan adalah peran utama dan yang merupakan peran dependen.

Properti navigasi menyediakan cara untuk menavigasi asosiasi antara dua jenis entitas. Setiap objek dapat memiliki properti navigasi untuk setiap hubungan tempat objek berpartisipasi. Properti navigasi memungkinkan Anda menavigasi dan mengelola hubungan di kedua arah, mengembalikan objek referensi (jika perkalian adalah satu atau nol-atau-satu) atau koleksi (jika perkaliannya banyak). Anda juga dapat memilih untuk memiliki navigasi satu arah, dalam hal ini Anda menentukan properti navigasi hanya pada salah satu jenis yang berpartisipasi dalam hubungan dan bukan pada keduanya.

Disarankan untuk menyertakan properti dalam model yang memetakan ke kunci asing dalam database. Dengan termasuk properti kunci asing, Anda dapat membuat atau mengubah hubungan dengan memodifikasi nilai kunci asing pada objek dependen. Asosiasi semacam ini disebut asosiasi kunci asing. Menggunakan kunci asing bahkan lebih penting ketika bekerja dengan entitas yang terputus. Perhatikan bahwa saat bekerja dengan 1-ke-1 atau 1-ke-0.. 1 hubungan, tidak ada kolom kunci asing terpisah, properti kunci utama bertindak sebagai kunci asing dan selalu disertakan dalam model.

Ketika kolom kunci asing tidak disertakan dalam model, informasi asosiasi dikelola sebagai objek independen. Hubungan dilacak melalui referensi objek alih-alih properti kunci asing. Jenis asosiasi ini disebut asosiasi independen. Cara paling umum untuk memodifikasi asosiasi independen adalah dengan memodifikasi properti navigasi yang dihasilkan untuk setiap entitas yang berpartisipasi dalam asosiasi.

Anda dapat memilih untuk menggunakan satu atau kedua jenis asosiasi dalam model Anda. Namun, jika Anda memiliki hubungan banyak-ke-banyak murni yang dihubungkan oleh tabel gabungan yang hanya berisi kunci asing, EF akan menggunakan asosiasi independen untuk mengelola hubungan banyak ke banyak tersebut.   

Gambar berikut menunjukkan model konseptual yang dibuat dengan Perancang Kerangka Kerja Entitas. Model ini berisi dua entitas yang berpartisipasi dalam hubungan satu-ke-banyak. Kedua entitas memiliki properti navigasi. Kursus adalah entitas dependen dan memiliki properti kunci asing DepartmentID yang ditentukan.

Department and Course tables with navigation properties

Cuplikan kode berikut menunjukkan model yang sama yang dibuat dengan Code First.

public class Course
{
  public int CourseID { get; set; }
  public string Title { get; set; }
  public int Credits { get; set; }
  public int DepartmentID { get; set; }
  public virtual Department Department { get; set; }
}

public class Department
{
   public Department()
   {
     this.Courses = new HashSet<Course>();
   }  
   public int DepartmentID { get; set; }
   public string Name { get; set; }
   public decimal Budget { get; set; }
   public DateTime StartDate { get; set; }
   public int? Administrator {get ; set; }
   public virtual ICollection<Course> Courses { get; set; }
}

Mengonfigurasi atau memetakan hubungan

Sisa halaman ini mencakup cara mengakses dan memanipulasi data menggunakan hubungan. Untuk informasi tentang menyiapkan hubungan dalam model Anda, lihat halaman berikut ini.

Membuat dan memodifikasi hubungan

Dalam asosiasi kunci asing, ketika Anda mengubah hubungan, status objek dependen dengan status berubah menjadi EntityState.Unchanged EntityState.Modified. Dalam hubungan independen, mengubah hubungan tidak memperbarui status objek dependen.

Contoh berikut menunjukkan cara menggunakan properti kunci asing dan properti navigasi untuk mengaitkan objek terkait. Dengan asosiasi kunci asing, Anda dapat menggunakan salah satu metode untuk mengubah, membuat, atau memodifikasi hubungan. Dengan asosiasi independen, Anda tidak dapat menggunakan properti kunci asing.

  • Dengan menetapkan nilai baru ke properti kunci asing, seperti dalam contoh berikut.

    course.DepartmentID = newCourse.DepartmentID;
    
  • Kode berikut menghapus hubungan dengan mengatur kunci asing ke null. Perhatikan, bahwa properti kunci asing harus nullable.

    course.DepartmentID = null;
    

    Catatan

    Jika referensi dalam status ditambahkan (dalam contoh ini, objek kursus), properti navigasi referensi tidak akan disinkronkan dengan nilai kunci objek baru sampai SaveChanges dipanggil. Sinkronisasi tidak terjadi karena konteks objek tidak berisi kunci permanen untuk objek yang ditambahkan hingga disimpan. Jika Anda harus memiliki objek baru yang sepenuhnya disinkronkan segera setelah Anda mengatur hubungan, gunakan salah satu metode berikut.*

  • Dengan menetapkan objek baru ke properti navigasi. Kode berikut membuat hubungan antara kursus dan department. Jika objek dilampirkan ke konteks, course juga ditambahkan ke department.Courses koleksi, dan properti kunci asing yang sesuai pada course objek diatur ke nilai properti kunci departemen.

    course.Department = department;
    
  • Untuk menghapus hubungan, atur properti navigasi ke null. Jika Anda bekerja dengan Entity Framework yang didasarkan pada .NET 4.0, maka akhir terkait perlu dimuat sebelum Anda mengaturnya ke null. Contohnya:

    context.Entry(course).Reference(c => c.Department).Load();
    course.Department = null;
    

    Dimulai dengan Entity Framework 5.0, yang didasarkan pada .NET 4.5, Anda dapat mengatur hubungan ke null tanpa memuat akhir terkait. Anda juga dapat mengatur nilai saat ini ke null menggunakan metode berikut.

    context.Entry(course).Reference(c => c.Department).CurrentValue = null;
    
  • Dengan menghapus atau menambahkan objek dalam kumpulan entitas. Misalnya, Anda dapat menambahkan objek jenis Course ke department.Courses koleksi. Operasi ini menciptakan hubungan antara kursus tertentu dan tertentu department. Jika objek dilampirkan ke konteks, referensi departemen dan properti kunci asing pada objek kursus akan diatur ke yang sesuai department.

    department.Courses.Add(newCourse);
    
  • Dengan menggunakan ChangeRelationshipState metode untuk mengubah status hubungan yang ditentukan antara dua objek entitas. Metode ini paling umum digunakan saat bekerja dengan aplikasi N-Tingkat dan asosiasi independen (tidak dapat digunakan dengan asosiasi kunci asing). Selain itu, untuk menggunakan metode ini, Anda harus turun ke ObjectContext, seperti yang ditunjukkan pada contoh di bawah ini.
    Dalam contoh berikut, ada hubungan banyak ke banyak antara Instruktur dan Kursus. Memanggil ChangeRelationshipState metode dan meneruskan EntityState.Added parameter, memberi SchoolContext tahu bahwa hubungan telah ditambahkan di antara dua objek:

    
    ((IObjectContextAdapter)context).ObjectContext.
      ObjectStateManager.
      ChangeRelationshipState(course, instructor, c => c.Instructor, EntityState.Added);
    

    Perhatikan bahwa jika Anda memperbarui (bukan hanya menambahkan) hubungan, Anda harus menghapus hubungan lama setelah menambahkan yang baru:

    ((IObjectContextAdapter)context).ObjectContext.
      ObjectStateManager.
      ChangeRelationshipState(course, oldInstructor, c => c.Instructor, EntityState.Deleted);
    

Menyinkronkan perubahan antara kunci asing dan properti navigasi

Saat Anda mengubah hubungan objek yang dilampirkan ke konteks dengan menggunakan salah satu metode yang dijelaskan di atas, Kerangka Kerja Entitas perlu menjaga kunci asing, referensi, dan koleksi tetap sinkron. Entity Framework secara otomatis mengelola sinkronisasi ini (juga dikenal sebagai perbaikan hubungan) untuk entitas POCO dengan proksi. Untuk informasi selengkapnya, lihat Bekerja dengan Proksi.

Jika Anda menggunakan entitas POCO tanpa proksi, Anda harus memastikan bahwa metode DetectChanges dipanggil untuk menyinkronkan objek terkait dalam konteks. Perhatikan bahwa API berikut secara otomatis memicu panggilan DetectChanges .

  • DbSet.Add
  • DbSet.AddRange
  • DbSet.Remove
  • DbSet.RemoveRange
  • DbSet.Find
  • DbSet.Local
  • DbContext.SaveChanges
  • DbSet.Attach
  • DbContext.GetValidationErrors
  • DbContext.Entry
  • DbChangeTracker.Entries
  • Menjalankan kueri LINQ terhadap DbSet

Dalam Kerangka Kerja Entitas, Anda biasanya menggunakan properti navigasi untuk memuat entitas yang terkait dengan entitas yang dikembalikan oleh asosiasi yang ditentukan. Untuk informasi selengkapnya, baca Memuat Objek Terkait.

Catatan

Dalam asosiasi kunci asing, ketika Anda memuat akhir terkait dari objek dependen, objek terkait akan dimuat berdasarkan nilai kunci asing dependen yang saat ini berada dalam memori:

    // Get the course where currently DepartmentID = 2.
    Course course = context.Courses.First(c => c.DepartmentID == 2);

    // Use DepartmentID foreign key property
    // to change the association.
    course.DepartmentID = 3;

    // Load the related Department where DepartmentID = 3
    context.Entry(course).Reference(c => c.Department).Load();

Dalam asosiasi independen, akhir terkait objek dependen dikueri berdasarkan nilai kunci asing yang saat ini ada dalam database. Namun, jika hubungan dimodifikasi, dan properti referensi pada objek dependen menunjuk ke objek utama berbeda yang dimuat dalam konteks objek, Kerangka Kerja Entitas akan mencoba membuat hubungan seperti yang didefinisikan pada klien.

Mengelola konkurensi

Dalam asosiasi kunci asing dan independen, pemeriksaan konkurensi didasarkan pada kunci entitas dan properti entitas lain yang ditentukan dalam model. Saat menggunakan EF Designer untuk membuat model, atur ConcurrencyMode atribut ke tetap untuk menentukan bahwa properti harus diperiksa konkurensinya. Saat menggunakan Kode Pertama untuk menentukan model, gunakan ConcurrencyCheck anotasi pada properti yang ingin Anda periksa konkurensinya. Saat bekerja dengan Code First, Anda juga dapat menggunakan TimeStamp anotasi untuk menentukan bahwa properti harus diperiksa konkurensinya. Anda hanya dapat memiliki satu properti tanda waktu di kelas tertentu. Kode Pertama memetakan properti ini ke bidang yang tidak dapat diubah ke null dalam database.

Kami menyarankan agar Anda selalu menggunakan asosiasi kunci asing saat bekerja dengan entitas yang berpartisipasi dalam pemeriksaan dan resolusi konkurensi.

Untuk informasi selengkapnya, lihat Menangani Konflik Konkurensi.

Bekerja dengan Kunci yang tumpang tindih

Kunci yang tumpang tindih adalah kunci komposit di mana beberapa properti dalam kunci juga merupakan bagian dari kunci lain dalam entitas. Anda tidak dapat memiliki kunci yang tumpang tindih dalam asosiasi independen. Untuk mengubah asosiasi kunci asing yang mencakup kunci yang tumpang tindih, kami sarankan Anda memodifikasi nilai kunci asing alih-alih menggunakan referensi objek.