Entity Framework 4, POCO object dan ASP.Net MVC2. Saya memiliki hubungan banyak ke banyak, katakanlah antara BlogPost dan entitas Tag. Ini berarti bahwa di kelas BlogPost POCO yang dihasilkan T4 saya, saya memiliki:
public virtual ICollection<Tag> Tags {
// getter and setter with the magic FixupCollection
}
private ICollection<Tag> _tags;
Saya meminta BlogPost dan Tag terkait dari instance ObjectContext dan mengirimkannya ke lapisan lain (Lihat di aplikasi MVC). Kemudian saya mendapatkan kembali BlogPost yang diperbarui dengan properti yang diubah dan hubungan yang diubah. Misalnya memiliki tag "A" "B" dan "C", dan tag baru adalah "C" dan "D". Dalam contoh khusus saya, tidak ada Tag baru dan properti Tag tidak pernah berubah, jadi satu-satunya hal yang harus disimpan adalah hubungan yang diubah. Sekarang saya perlu menyimpan ini di ObjectContext lain. (Pembaruan: Sekarang saya mencoba melakukan dalam contoh konteks yang sama dan juga gagal.)
Masalahnya: Saya tidak bisa membuatnya menyelamatkan hubungan dengan benar. Saya mencoba semua yang saya temukan:
- Controller.UpdateModel dan Controller.TryUpdateModel tidak berfungsi.
- Mendapatkan BlogPost lama dari konteks lalu mengubah koleksi tidak berfungsi. (dengan metode berbeda dari poin berikutnya)
- Ini mungkin akan berhasil, tapi saya harap ini hanya solusi, bukan solusinya :(.
- Mencoba fungsi Attach / Add / ChangeObjectState untuk BlogPost dan / atau Tag di setiap kemungkinan kombinasi. Gagal.
- Ini terlihat seperti yang saya butuhkan, tetapi tidak berhasil (saya mencoba memperbaikinya, tetapi tidak bisa untuk masalah saya).
- Mencoba ChangeState / Add / Attach / ... objek hubungan konteks. Gagal.
"Tidak berfungsi" berarti dalam banyak kasus bahwa saya mengerjakan "solusi" yang diberikan hingga tidak menghasilkan kesalahan dan setidaknya menyimpan properti BlogPost. Apa yang terjadi dengan hubungan bervariasi: biasanya Tag ditambahkan lagi ke tabel Tag dengan PK baru dan BlogPost yang disimpan mereferensikannya dan bukan yang asli. Tentu saja Tag yang dikembalikan memiliki PK, dan sebelum metode simpan / perbarui saya memeriksa PK dan mereka sama dengan yang ada di database sehingga mungkin EF berpikir bahwa mereka adalah objek baru dan PK tersebut adalah temp sementara.
Masalah yang saya ketahui dan mungkin tidak memungkinkan untuk menemukan solusi sederhana otomatis: Ketika koleksi objek POCO diubah, itu seharusnya terjadi oleh properti koleksi virtual yang disebutkan di atas, karena trik FixupCollection akan memperbarui referensi terbalik di ujung lain dari hubungan banyak-ke-banyak. Namun, saat Tampilan "mengembalikan" objek BlogPost yang diperbarui, hal itu tidak terjadi. Ini berarti mungkin tidak ada solusi sederhana untuk masalah saya, tetapi itu akan membuat saya sangat sedih dan saya akan membenci kemenangan EF4-POCO-MVC :(. Itu juga berarti EF tidak dapat melakukan ini di lingkungan MVC mana pun Jenis objek EF4 digunakan :(. Saya pikir pelacakan perubahan berbasis snapshot seharusnya mengetahui bahwa BlogPost yang diubah memiliki hubungan ke Tag dengan PK yang ada.
Btw: Saya pikir masalah yang sama terjadi dengan hubungan satu-ke-banyak (google dan kolega saya bilang begitu). Saya akan mencobanya di rumah, tetapi meskipun berhasil, itu tidak membantu saya dalam enam hubungan banyak-ke-banyak di aplikasi saya :(.
sumber
Jawaban:
Mari kita coba dengan cara ini:
Edit:
Saya kira salah satu komentar saya memberi Anda harapan palsu bahwa EF akan melakukan penggabungan untuk Anda. Saya banyak bermain dengan masalah ini dan kesimpulan saya mengatakan EF tidak akan melakukan ini untuk Anda. Saya rasa Anda juga telah menemukan pertanyaan saya di MSDN . Pada kenyataannya ada banyak pertanyaan seperti itu di Internet. Masalahnya adalah tidak dijelaskan secara jelas bagaimana menangani skenario ini. Jadi mari kita lihat masalahnya:
Latar belakang masalah
EF perlu melacak perubahan pada entitas sehingga persistensi mengetahui rekaman mana yang harus diperbarui, disisipkan atau dihapus. Masalahnya adalah bahwa ObjectContext bertanggung jawab untuk melacak perubahan. ObjectContext dapat melacak perubahan hanya untuk entitas terlampir. Entitas yang dibuat di luar ObjectContext tidak dilacak sama sekali.
Deskripsi masalah
Berdasarkan uraian di atas, kami dapat dengan jelas menyatakan bahwa EF lebih cocok untuk skenario terhubung di mana entitas selalu dilampirkan ke konteks - khas untuk aplikasi WinForm. Aplikasi web memerlukan skenario terputus di mana konteks ditutup setelah pemrosesan permintaan dan konten entitas diteruskan sebagai respons HTTP ke klien. Permintaan HTTP berikutnya menyediakan konten entitas yang dimodifikasi yang harus dibuat ulang, dilampirkan ke konteks baru dan dipertahankan. Rekreasi biasanya terjadi di luar cakupan konteks (arsitektur berlapis dengan ketidaktahuan ketekunan).
Larutan
Jadi bagaimana menangani skenario terputus seperti itu? Saat menggunakan kelas POCO, kami memiliki 3 cara untuk menangani pelacakan perubahan:
Sinkronisasi manual pada entitas tunggal adalah tugas yang mudah. Anda hanya perlu melampirkan entitas dan memanggil AddObject untuk memasukkan, DeleteObject untuk menghapus atau menyetel status di ObjectStateManager ke Modified untuk memperbarui. Rasa sakit yang sebenarnya datang ketika Anda harus berurusan dengan grafik objek, bukan entitas tunggal. Rasa sakit ini bahkan lebih buruk ketika Anda harus berurusan dengan asosiasi independen (yang tidak menggunakan properti Foreign Key) dan banyak ke banyak relasi. Dalam hal ini Anda harus menyinkronkan setiap entitas secara manual dalam grafik objek tetapi juga setiap relasi dalam grafik objek.
Sinkronisasi manual diusulkan sebagai solusi oleh dokumentasi MSDN: Memasang dan Melepaskan objek mengatakan:
Metode yang disebutkan adalah ChangeObjectState dan ChangeRelationshipState dari ObjectStateManager = pelacakan perubahan manual. Proposal serupa ada di artikel dokumentasi MSDN lainnya: Mendefinisikan dan Mengelola Hubungan mengatakan:
Selain itu ada posting blog terkait EF v1 yang mengkritik perilaku EF ini.
Alasan solusi
EF memiliki banyak "membantu" operasi dan pengaturan seperti Segarkan , beban , ApplyCurrentValues , ApplyOriginalValues , MergeOption dll Tapi oleh penyelidikan saya semua fitur ini bekerja hanya untuk entitas tunggal dan hanya mempengaruhi preperties skalar (= tidak sifat navigasi dan hubungan). Saya lebih suka tidak menguji metode ini dengan tipe kompleks yang bersarang di entitas.
Solusi lain yang diusulkan
Alih-alih fungsi Merge yang sebenarnya, tim EF menyediakan sesuatu yang disebut Self Tracking Entities (STE) yang tidak memecahkan masalah. Pertama-tama STE hanya berfungsi jika instance yang sama digunakan untuk seluruh pemrosesan. Dalam aplikasi web, hal ini tidak terjadi kecuali Anda menyimpan instance dalam status tampilan atau sesi. Karena itu saya sangat tidak senang menggunakan EF dan saya akan memeriksa fitur-fitur NHibernate. Pengamatan pertama mengatakan bahwa NHibernate mungkin memiliki fungsi seperti itu .
Kesimpulan
Saya akan mengakhiri asumsi ini dengan tautan tunggal ke pertanyaan terkait lainnya di forum MSDN. Periksa jawaban Zeeshan Hirani. Dia adalah penulis dari Entity Framework 4.0 Recipes . Jika dia mengatakan bahwa penggabungan otomatis grafik objek tidak didukung, saya percaya padanya.
Tetapi masih ada kemungkinan bahwa saya sepenuhnya salah dan beberapa fungsi penggabungan otomatis ada di EF.
Edit 2:
Seperti yang Anda lihat, ini telah ditambahkan ke MS Connect sebagai saran pada tahun 2007. MS telah menutupnya sebagai sesuatu yang harus dilakukan di versi berikutnya tetapi sebenarnya tidak ada yang dilakukan untuk memperbaiki celah ini kecuali STE.
sumber
Saya memiliki solusi untuk masalah yang dijelaskan di atas oleh Ladislav. Saya telah membuat metode ekstensi untuk DbContext yang secara otomatis akan melakukan penambahan / perbarui / hapus berdasarkan perbedaan grafik yang disediakan dan grafik tetap.
Silakan lihat dan lihat apakah itu dapat membantu http://refactorthis.wordpress.com/2012/12/11/introducing-graphdiff-for-entity-framework-code-first-allowing-automated-updates-of-a- grafik-entitas-terpisah /
Anda dapat langsung membuka kodenya di sini https://github.com/refactorthis/GraphDiff
sumber
Saya tahu ini terlambat untuk OP tetapi karena ini adalah masalah yang sangat umum, saya memposting ini jika melayani orang lain. Saya telah bermain-main dengan masalah ini dan saya pikir saya mendapat solusi yang cukup sederhana, yang saya lakukan adalah:
Dalam contoh berikut "dataobj" dan "_categories" adalah parameter yang diterima oleh pengontrol saya "dataobj" adalah objek utama saya, dan "_categories" adalah IEnumerable yang berisi ID kategori yang dipilih pengguna dalam tampilan.
Ia bahkan bekerja untuk banyak relasi
sumber
Tim Entity Framework menyadari bahwa ini adalah masalah kegunaan dan berencana untuk mengatasinya setelah EF6.
Dari tim Entity Framework:
Jika hal ini memengaruhi Anda, berikan suara untuk fitur di
http://entityframework.codeplex.com/workitem/864
sumber
Semua jawaban bagus untuk menjelaskan masalah, tetapi tidak ada yang benar-benar menyelesaikan masalah untuk saya.
Saya menemukan bahwa jika saya tidak menggunakan relasi di entitas induk tetapi hanya menambahkan dan menghapus entitas anak, semuanya berfungsi dengan baik.
Maaf untuk VB, tapi di situlah proyek yang saya kerjakan ditulis.
Entitas induk "Report" memiliki hubungan satu ke banyak dengan "ReportRole" dan memiliki properti "ReportRoles". Peran baru diteruskan oleh string yang dipisahkan koma dari panggilan Ajax.
Baris pertama akan menghapus semua entitas anak, dan jika saya menggunakan "report.ReportRoles.Remove (f)" bukan "db.ReportRoles.Remove (f)" Saya akan mendapatkan kesalahan.
sumber