Saat menjalankan SubmitChanges ke DataContext setelah memperbarui beberapa properti dengan sambungan LINQ ke SQL (terhadap SQL Server Compact Edition) saya mendapatkan "Baris tidak ditemukan atau diubah." ChangeConflictException.
var ctx = new Data.MobileServerDataDataContext(Common.DatabasePath);
var deviceSessionRecord = ctx.Sessions.First(sess => sess.SessionRecId == args.DeviceSessionId);
deviceSessionRecord.IsActive = false;
deviceSessionRecord.Disconnected = DateTime.Now;
ctx.SubmitChanges();
Kueri menghasilkan SQL berikut ini:
UPDATE [Sessions]
SET [Is_Active] = @p0, [Disconnected] = @p1
WHERE 0 = 1
-- @p0: Input Boolean (Size = 0; Prec = 0; Scale = 0) [False]
-- @p1: Input DateTime (Size = 0; Prec = 0; Scale = 0) [9/4/2008 5:12:02 PM]
-- Context: SqlProvider(SqlCE) Model: AttributedMetaModel Build: 3.5.21022.8
Masalah yang jelas adalah WHERE 0 = 1 , Setelah record dimuat, saya telah mengonfirmasi bahwa semua properti di "deviceSessionRecord" sudah benar untuk menyertakan kunci utama. Juga saat menangkap "ChangeConflictException" tidak ada informasi tambahan tentang mengapa ini gagal. Saya juga mengonfirmasi bahwa pengecualian ini dilemparkan dengan tepat satu catatan dalam database (catatan yang saya coba perbarui)
Yang aneh adalah bahwa saya memiliki pernyataan pembaruan yang sangat mirip di bagian kode yang berbeda dan menghasilkan SQL berikut ini dan memang memperbarui database SQL Server Compact Edition saya.
UPDATE [Sessions]
SET [Is_Active] = @p4, [Disconnected] = @p5
WHERE ([Session_RecId] = @p0) AND ([App_RecId] = @p1) AND ([Is_Active] = 1) AND ([Established] = @p2) AND ([Disconnected] IS NULL) AND ([Member_Id] IS NULL) AND ([Company_Id] IS NULL) AND ([Site] IS NULL) AND (NOT ([Is_Device] = 1)) AND ([Machine_Name] = @p3)
-- @p0: Input Guid (Size = 0; Prec = 0; Scale = 0) [0fbbee53-cf4c-4643-9045-e0a284ad131b]
-- @p1: Input Guid (Size = 0; Prec = 0; Scale = 0) [7a174954-dd18-406e-833d-8da650207d3d]
-- @p2: Input DateTime (Size = 0; Prec = 0; Scale = 0) [9/4/2008 5:20:50 PM]
-- @p3: Input String (Size = 0; Prec = 0; Scale = 0) [CWMOBILEDEV]
-- @p4: Input Boolean (Size = 0; Prec = 0; Scale = 0) [False]
-- @p5: Input DateTime (Size = 0; Prec = 0; Scale = 0) [9/4/2008 5:20:52 PM]
-- Context: SqlProvider(SqlCE) Model: AttributedMetaModel Build: 3.5.21022.8
Saya telah mengkonfirmasi bahwa nilai bidang utama yang tepat telah diidentifikasi di Skema Database dan DBML yang menghasilkan kelas LINQ.
Saya kira ini hampir merupakan pertanyaan dua bagian:
- Mengapa pengecualian itu dilempar?
- Setelah meninjau set kedua dari SQL yang dihasilkan, sepertinya untuk mendeteksi konflik akan lebih baik untuk memeriksa semua bidang, tetapi saya membayangkan ini akan menjadi cukup tidak efisien. Apakah ini cara yang selalu berhasil? Apakah ada pengaturan untuk memeriksa kunci utama?
Saya telah berjuang dengan ini selama dua jam terakhir sehingga bantuan apa pun akan sangat kami hargai.
sumber
Jawaban:
Itu buruk, tapi sederhana:
Periksa apakah tipe data untuk semua bidang di O / R-Designer cocok dengan tipe data di tabel SQL Anda. Periksa ulang untuk nullable! Kolom harus berupa nullable baik di O / R-Designer dan SQL, atau tidak nullable di keduanya.
Misalnya, kolom "judul" NVARCHAR ditandai sebagai NULLable dalam database Anda, dan berisi nilai NULL. Meskipun kolom tersebut ditandai sebagai NOT NULLable di O / R-Mapping Anda, LINQ akan memuatnya dengan sukses dan mengatur kolom-String ke null.
Gejala yang sama akan muncul ketika tipe data bidang tidak cocok dengan tipe data dalam SQL, atau jika bidang hilang, karena LINQ tidak akan dapat memastikan data SQL tidak berubah sejak membaca data.
sumber
VARCHAR(MAX) NOT NULL
menjadiVARCHAR(MAX) NULL
dan mengharapkannya berfungsi. Kesalahan yang sangat sederhana.NUMERIC(12,8)
kolom yang dipetakan keDecimal
properti. Saya harus tepat DbType di atribut Kolom[Column(DbType="numeric(12,8)")] public decimal? MyProperty ...
Pertama, penting untuk diketahui, apa yang menyebabkan masalah. Solusi Googling akan membantu, Anda dapat mencatat detail (tabel, kolom, nilai lama, nilai baru) tentang konflik untuk menemukan solusi yang lebih baik untuk menyelesaikan konflik nanti:
Buat pembantu untuk membungkus sumbitChanges Anda:
Dan kemudian panggil kirim kode perubahan:
Terakhir, catat pengecualian di penangan pengecualian global Anda:
sumber
Ada metode di DataContext yang disebut Refresh yang dapat membantu di sini. Ini memungkinkan Anda memuat ulang rekaman database sebelum perubahan dikirimkan, dan menawarkan mode berbeda untuk menentukan nilai mana yang akan disimpan. "KeepChanges" tampaknya yang paling cerdas untuk tujuan saya, ini dimaksudkan untuk menggabungkan perubahan saya dengan perubahan yang tidak bertentangan yang terjadi di database untuk sementara.
Jika saya memahaminya dengan benar. :)
sumber
dc.Refresh(RefreshMode.KeepChanges,changedObject);
sebelum dc.SubmitChangesIni juga bisa disebabkan oleh penggunaan lebih dari satu DbContext.
Jadi contohnya:
Kode ini akan gagal dari waktu ke waktu, dengan cara yang tampaknya tidak dapat diprediksi, karena pengguna digunakan dalam kedua konteks, diubah dan disimpan di satu konteks, lalu disimpan di konteks lain. Representasi dalam memori dari pengguna yang memiliki "Sesuatu" tidak cocok dengan apa yang ada di database, sehingga Anda mendapatkan bug yang mengintai ini.
Salah satu cara untuk mencegahnya adalah dengan menulis kode apa pun yang mungkin pernah disebut sebagai metode pustaka sedemikian rupa sehingga membutuhkan DbContext opsional:
Jadi sekarang metode Anda menggunakan database opsional, dan jika tidak ada, pergi dan membuatnya sendiri. Jika ada, itu hanya menggunakan kembali apa yang telah diteruskan. Metode helper memudahkan untuk menggunakan kembali pola ini di seluruh aplikasi Anda.
sumber
Saya memecahkan kesalahan ini dengan menyeret ulang tabel dari penjelajah server ke perancang dan membangun kembali.
sumber
Inilah yang Anda butuhkan untuk mengganti kesalahan ini pada kode C #:
sumber
Saya tidak tahu apakah Anda telah menemukan jawaban yang memuaskan untuk pertanyaan Anda, tetapi saya memposting pertanyaan serupa dan akhirnya menjawabnya sendiri. Ternyata opsi koneksi default NOCOUNT diaktifkan untuk database, yang menyebabkan ChangeConflictException untuk setiap pembaruan yang dibuat dengan Linq ke Sql. Anda dapat merujuk ke posting saya di sini .
sumber
Saya memperbaiki ini dengan menambahkan
(UpdateCheck = UpdateCheck.Never)
ke semua[Column]
definisi.Tidak terasa seperti solusi yang tepat. Dalam kasus saya ini tampaknya terkait dengan fakta bahwa tabel ini memiliki asosiasi ke tabel lain dari mana baris dihapus.
Ini ada di Windows Phone 7.5.
sumber
Dalam kasus saya, kesalahan muncul ketika dua pengguna yang memiliki konteks data LINQ-ke-SQL yang berbeda memperbarui entitas yang sama dengan cara yang sama. Ketika pengguna kedua mencoba pembaruan, salinan yang mereka miliki dalam konteks datanya sudah usang meskipun itu dibaca setelah pembaruan pertama selesai.
Saya menemukan penjelasan dan solusi dalam artikel ini oleh Akshay Phadke: https://www.c-sharpcorner.com/article/overview-of-concurrency-in-linq-to-sql/
Inilah kode yang paling sering saya angkat:
Ketika saya melihat jendela keluaran saya saat debugging, saya bisa melihat bahwa Nilai Saat Ini cocok dengan Nilai Database. "Nilai Asli" selalu menjadi pelakunya. Itu adalah nilai yang dibaca oleh konteks data sebelum menerapkan pembaruan.
Terima kasih kepada MarceloBarbosa atas inspirasinya.
sumber
Saya tahu pertanyaan ini sudah lama dijawab tetapi di sini saya telah menghabiskan beberapa jam terakhir membenturkan kepala ke dinding dan saya hanya ingin membagikan solusi saya yang ternyata tidak terkait dengan salah satu item di utas ini:
Caching!
Bagian select () dari objek data saya menggunakan caching. Saat memperbarui objek, kesalahan Row Not Found or Changed telah muncul.
Beberapa jawaban memang menyebutkan menggunakan DataContext yang berbeda dan dalam retrospeksi mungkin inilah yang terjadi tetapi itu tidak langsung membuat saya berpikir caching jadi mudah-mudahan ini akan membantu seseorang!
sumber
Saya baru-baru ini mengalami kesalahan ini, dan menemukan bahwa masalahnya bukan pada Konteks Data saya, tetapi dengan pernyataan pembaruan yang diaktifkan di dalam pemicu setelah Komit dipanggil pada Konteks. Pemicu mencoba memperbarui bidang yang tidak dapat dinolkan dengan nilai nol, dan itu menyebabkan kesalahan konteks dengan pesan yang disebutkan di atas.
Saya menambahkan jawaban ini semata-mata untuk membantu orang lain mengatasi kesalahan ini dan tidak menemukan resolusi dalam jawaban di atas.
sumber
Saya juga mendapatkan kesalahan ini karena menggunakan dua konteks yang berbeda. Saya menyelesaikan masalah ini dengan menggunakan konteks data tunggal.
sumber
Dalam kasus saya, masalahnya adalah dengan opsi pengguna di seluruh server. Berikut:
https://msdn.microsoft.com/en-us/library/ms190763.aspx
Saya mengaktifkan opsi NOCOUNT dengan harapan mendapatkan beberapa manfaat kinerja:
dan ini ternyata mematahkan pemeriksaan Linq untuk Baris yang Terkena Dampak (sebanyak yang saya bisa ketahui dari sumber .NET), yang mengarah ke ChangeConflictException
Mengatur ulang opsi untuk mengecualikan 512 bit memperbaiki masalah.
sumber
Setelah menggunakan jawaban qub1n, saya menemukan bahwa masalah bagi saya adalah saya secara tidak sengaja menyatakan kolom database menjadi desimal (18,0). Saya menetapkan nilai desimal, tetapi database mengubahnya, menghapus bagian desimal. Hal ini mengakibatkan masalah berganti baris.
Tambahkan saja ini jika ada orang lain yang mengalami masalah serupa.
sumber
gunakan saja Linq2DB, jauh lebih baik
sumber