Sisipkan / Perbarui Banyak ke Banyak Kerangka Entitas. Bagaimana saya melakukannya?

104

Saya menggunakan EF4 dan baru mengenalnya. Saya memiliki banyak atau banyak dalam proyek saya dan sepertinya tidak dapat mengetahui cara memasukkan atau memperbarui. Saya telah membangun sebuah proyek kecil hanya untuk melihat bagaimana itu harus diberi kode.

Misalkan saya memiliki 3 tabel

  1. Kelas: ClassID-ClassName
  2. Mahasiswa: StudentID-FirstName-Surname
  3. StudentClass: StudentID-ClassID

Setelah menambahkan semua hubungan dan memperbarui model melalui model browser saya perhatikan bahwa StudentClass tidak muncul, ini tampaknya perilaku default.

Sekarang saya perlu melakukan Sisipan dan Pembaruan. Bagaimana Anda melakukannya? Ada contoh kode atau tautan tempat saya dapat mengunduh contoh, atau dapatkah Anda meluangkan waktu 5 menit?

pengguna9969
sumber

Jawaban:

139

Dalam istilah entitas (atau objek) Anda memiliki Classobjek yang memiliki koleksi Studentsdan Studentobjek yang memiliki koleksi Classes. Karena StudentClasstabel Anda hanya berisi Id dan tidak ada informasi tambahan, EF tidak menghasilkan entitas untuk tabel penggabungan. Itu adalah perilaku yang benar dan itulah yang Anda harapkan.

Sekarang, ketika melakukan penyisipan atau pembaruan, cobalah untuk berpikir dalam kerangka objek. Misalnya jika Anda ingin memasukkan kelas dengan dua siswa, buat Classobjek, Studentobjek, tambahkan siswa ke Studentskoleksi kelas tambahkan Classobjek ke konteks dan panggil SaveChanges:

using (var context = new YourContext())
{
    var mathClass = new Class { Name = "Math" };
    mathClass.Students.Add(new Student { Name = "Alice" });
    mathClass.Students.Add(new Student { Name = "Bob" });

    context.AddToClasses(mathClass);
    context.SaveChanges();
}

Ini akan membuat entri di Classtabel, dua entri di Studenttabel dan dua entri di StudentClasstabel yang menghubungkan keduanya.

Anda pada dasarnya melakukan hal yang sama untuk pembaruan. Ambil saja datanya, ubah grafik dengan menambahkan dan menghapus objek dari koleksi, panggil SaveChanges. Periksa pertanyaan serupa ini untuk detailnya.

Edit :

Menurut komentar Anda, Anda perlu memasukkan yang baru Classdan menambahkan dua yang sudah ada Students:

using (var context = new YourContext())
{
    var mathClass= new Class { Name = "Math" };
    Student student1 = context.Students.FirstOrDefault(s => s.Name == "Alice");
    Student student2 = context.Students.FirstOrDefault(s => s.Name == "Bob");
    mathClass.Students.Add(student1);
    mathClass.Students.Add(student2);

    context.AddToClasses(mathClass);
    context.SaveChanges();
}

Karena kedua siswa sudah ada dalam database, mereka tidak akan disisipkan, tetapi karena mereka sekarang berada dalam Studentskumpulan Class, dua entri akan disisipkan ke dalam StudentClasstabel.

Yakimych
sumber
Hai, Terima kasih atas balasan Anda. Skenario saya adalah bahwa saya harus memasukkan 1 entri ke kelas dan sebagai x contoh Anda 2 entri ke StudentClass dan tidak ada entri ke Student. Saya bingung bagaimana saya melakukannya
user9969
ITU BEKERJA A MENGOBATI. Mengenai pembaruan. Adakah hal istimewa yang perlu saya lakukan? Misalnya, cukup memperbarui className misalnya.
pengguna9969
3
Ini akan menambah overhead pengambilan item yang perlu ditambahkan dari database. Metode Lampirkan hanya dapat digunakan untuk menambahkan relasi. Lihat msdn.microsoft.com/en-us/data/jj592676.aspx dan juga stackoverflow.com/questions/11355019/…
Gnomo
3
AddToClasses adalah DbSet untuk Kelas?
Jo Smo
1
Jangan lupa untuk menginisialisasi koleksi Anda di konstruktor untuk Kelas dan Siswa. Misalnya: public Class () {this.Students = new HashSet <Student> (); }
pengguna1040323
40

Coba yang ini untuk Memperbarui:

[HttpPost]
public ActionResult Edit(Models.MathClass mathClassModel)
{
    //get current entry from db (db is context)
    var item = db.Entry<Models.MathClass>(mathClassModel);

    //change item state to modified
    item.State = System.Data.Entity.EntityState.Modified;

    //load existing items for ManyToMany collection
    item.Collection(i => i.Students).Load();

    //clear Student items          
    mathClassModel.Students.Clear();

    //add Toner items
    foreach (var studentId in mathClassModel.SelectedStudents)
    {
        var student = db.Student.Find(int.Parse(studentId));
        mathClassModel.Students.Add(student);
    }                

    if (ModelState.IsValid)
    {
       db.SaveChanges();
       return RedirectToAction("Index");
    }

    return View(mathClassModel);
}
Stritof
sumber
ini menyelamatkan hari saya terima kasih !!! mereka bagian kunci menjadi item.Collection (i => i.Students) .Load (); bagian
Gerrie Pretorius
Sekadar catatan, saya mengalami InvalidOperationException saat melakukan itu, sesuatu seperti entitas saya tidak ada dalam konteksnya. Saya baru saja menelepon context.MyEntityCollection.Attach (myEntity) untuk menanganinya.
Kilazur
Tidak akan pernah tahu itu. Terima kasih banyak.
Pantai Jared
1
Izinkan saya untuk menambahkan terima kasih saya di sini. Saya menulis & menguji lebih dari 130 baris kode selama 4 hari terakhir mencoba menyelesaikan tugas ini tetapi tidak dapat melakukannya. Mencoba ini dan semuanya bekerja dengan sempurna. Meskipun saya tidak memahami tujuan menetapkan variabel item dan kemudian tidak menggunakannya sama sekali, saya senang berhasil! Terima kasih sejuta bajillion !!!! :)
Dude-Dastic
Mengingat pertanyaannya adalah Sisipkan DAN Perbarui, jawaban ini melengkapi pertanyaan dan jawaban yang diterima. Terima kasih banyak!
Vahx
5

Saya ingin menambahkan pengalaman saya tentang itu. Memang EF, ketika Anda menambahkan objek ke konteks, itu mengubah status semua anak dan entitas terkait menjadi Ditambahkan. Meskipun ada pengecualian kecil dalam aturan di sini: jika anak / entitas terkait dilacak oleh konteks yang sama, EF memahami bahwa entitas ini ada dan tidak menambahkannya. Masalahnya terjadi ketika misalnya, Anda memuat anak-anak / entitas terkait dari beberapa konteks lain atau antarmuka web dll dan kemudian ya, EF tidak tahu apa-apa tentang entitas ini dan pergi dan menambahkan semuanya. Untuk menghindarinya, dapatkan saja kunci dari entitas dan temukan mereka (misalnya context.Students.FirstOrDefault(s => s.Name == "Alice"))dalam konteks yang sama di mana Anda ingin melakukan penambahan.

Athina
sumber
3

Saya menggunakan cara berikut untuk menangani hubungan banyak-ke-banyak di mana hanya kunci asing yang terlibat.

Jadi untuk memasukkan :

public void InsertStudentClass (long studentId, long classId)
{
    using (var context = new DatabaseContext())
    {
        Student student = new Student { StudentID = studentId };
        context.Students.Add(student);
        context.Students.Attach(student);

        Class class = new Class { ClassID = classId };
        context.Classes.Add(class);
        context.Classes.Attach(class);

        student.Classes = new List<Class>();
        student.Classes.Add(class);

        context.SaveChanges();
    }
}

Untuk menghapus ,

public void DeleteStudentClass(long studentId, long classId)
{
    Student student = context.Students.Include(x => x.Classes).Single(x => x.StudentID == studentId);

    using (var context = new DatabaseContext())
    {
        context.Students.Attach(student);
        Class classToDelete = student.Classes.Find(x => x.ClassID == classId);
        if (classToDelete != null)
        {
            student.Classes.Remove(classToDelete);
            context.SaveChanges();
        }
    }
}
lenglei
sumber
1

Dalam kerangka entitas, ketika objek ditambahkan ke konteks, statusnya berubah menjadi Ditambahkan. EF juga mengubah status setiap objek untuk ditambahkan dalam pohon objek dan karenanya Anda mendapatkan kesalahan pelanggaran kunci primer atau catatan duplikat ditambahkan dalam tabel.

Nilesh Hirapra
sumber
2
Harap edit untuk memberikan detail yang cukup sehingga pengguna tidak perlu mengunjungi blog Anda untuk mendapatkan jawabannya.