Kerangka Entitas: “Menyimpan pembaruan, menyisipkan, atau menghapus pernyataan memengaruhi jumlah baris yang tidak terduga (0).” [Tutup]

324

Saya menggunakan Entity Framework untuk mengisi kontrol kisi. Terkadang ketika saya melakukan pembaruan, saya mendapatkan kesalahan berikut:

Simpan pembaruan, masukkan, atau hapus pernyataan yang memengaruhi jumlah baris yang tidak terduga (0). Entitas mungkin telah dimodifikasi atau dihapus karena entitas dimuat. Segarkan entri ObjectStateManager.

Saya tidak tahu bagaimana cara mereproduksi ini. Tapi mungkin ada hubungannya dengan seberapa dekat saya membuat pembaruan. Adakah yang melihat ini atau apakah ada yang tahu apa yang dimaksud dengan pesan kesalahan?

Sunting: Sayangnya saya tidak lagi bebas untuk mereproduksi masalah yang saya alami di sini, karena saya menjauh dari proyek ini dan tidak ingat apakah saya akhirnya menemukan solusi, jika pengembang lain memperbaikinya, atau jika saya mengatasinya. Karena itu saya tidak dapat menerima jawaban apa pun.

pendapat kuat
sumber
Saya mendapatkan kesalahan ini dengan pengenalan kebijakan tingkat keamanan baris SQL Server yang memungkinkan pembaruan ke baris ke keadaan yang tidak dapat dibaca kembali (predikat FILTER eksklusif dengan predikat BLOK permisif) . EntityFramework membutuhkan baris yang diperbarui untuk dibaca kembali setelah pembaruan jika tidak menganggapnya sebagai kesalahan konkurensi (setidaknya saat menggunakan konkurensi optimis).
xr280xr
Masalahnya mungkin pelingkupan salah untuk DBContext Anda stackoverflow.com/questions/49154250/… (contoh ini untuk ASPNET Identity tetapi berlaku untuk konteks apa pun)
Simon_Weaver
Terlepas dari konteks kesalahan ini, merupakan ide bagus untuk meletakkan breakpoint di mana pun konteksnya sedang dipakai. Apakah Anda berharap itu akan dipakai sekali ketika Anda memuat halaman web tetapi itu mencapai breakpoint itu 5 kali? Maka Anda mungkin memiliki kondisi balapan. Lihatlah Request.Uriuntuk melihat URL permintaan yang sebenarnya. Dalam kasus saya, saya memiliki beberapa logika pelacakan yang mengenai situs saya dan tidak perlu memuat konteks dari DB (dan kadang-kadang memperbaruinya juga). Jadi, halaman sebenarnya yang saya debugging memiliki data yang diinjak oleh logika kode pelacakan bodoh.
Simon_Weaver
add @ Html.AntiForgeryToken () dalam tampilan
Vikas Sharma

Jawaban:

199

Itu adalah efek samping dari fitur yang disebut optimistic concurrency.

Tidak 100% yakin cara mengaktifkan / menonaktifkannya di Entity Framework tetapi pada dasarnya apa yang dikatakannya adalah bahwa antara saat Anda mengambil data dari database dan ketika Anda menyimpan perubahan, orang lain telah mengubah data (Yang berarti ketika Anda pergi untuk menyimpannya 0 baris benar-benar diperbarui). Dalam istilah SQL, klausa updatekueri mereka whereberisi nilai asli dari setiap bidang di baris, dan jika 0 baris terpengaruh, ia tahu ada yang salah.

Gagasan di baliknya adalah bahwa Anda tidak akan berakhir menimpa perubahan yang aplikasi Anda tidak tahu telah terjadi - itu pada dasarnya adalah langkah keamanan kecil yang dilemparkan oleh .NET pada semua pembaruan Anda.

Jika konsisten, kemungkinan itu terjadi dalam logika Anda sendiri (EG: Anda benar-benar memperbarui data sendiri dengan metode lain di antara seleksi dan pembaruan), tetapi itu bisa menjadi kondisi balapan antara dua aplikasi.

fyjham
sumber
34
Ini terjadi di lingkungan pengguna-tunggal (pada mesin dev saya) jadi saya tidak berpikir itu bisa menjadi kondisi balapan. Saya terikat ke kontrol kisi kustom dengan EntityDataSource jadi saya tidak yakin persis apa yang terjadi di balik layar, tapi saya tidak punya kode tambahan sendiri yang memodifikasi tabel. Apakah ada cara untuk mengubah pengaturan konkurensi ini?
strongopinions
3
Saya pikir Anda bisa berdasarkan per kolom pada model entitas Anda (Ada di jendela properti), tetapi masalahnya adalah itu hanya akan mencegah Anda melihat kesalahan dan masih tidak akan memperbarui apa pun. Apakah Anda dapat melihat perintah SQL ke database Anda (EG: SQL Server Profiler untuk MSSQL)? Dengan cara ini Anda bisa melihat pembaruan apa yang dihasilkannya dan harus bisa melihat mengapa pembaruan itu tidak memengaruhi baris apa pun.
fyjham
9
Jika entitas memiliki properti cap waktu, maka pastikan Anda menyimpannya di tampilan Anda dan pastikan entitas mengisi cap waktu dengan benar.
anIBMer
Saya memiliki kolom stempel waktu dan setelah saya mengatasinya, EF6.1 bekerja seperti yang diharapkan, terima kasih atas tipnya @ anelBMer
JQII
3
Jika Anda menggunakan cap waktu, objek yang ingin Anda hapus perlu set PK dan Properti RowVersion untuk memperbaruinya dengan sukses! Saya mengatur properti rowVersion (timestamp), setelah saya melampirkan objek ke masing-masing DbSet, itu sebabnya itu tidak berhasil. Kerja bagus!
Legenda
394

Saya berlari ke ini dan itu disebabkan oleh bidang ID (kunci) entitas tidak disetel. Jadi ketika konteksnya pergi untuk menyimpan data, itu tidak dapat menemukan ID = 0. Pastikan untuk menempatkan titik istirahat dalam pernyataan pembaruan Anda dan memverifikasi bahwa ID entitas telah ditetapkan.

Dari komentar Paul Bellora

Saya mengalami masalah ini, karena lupa memasukkan input ID tersembunyi di halaman edit .cshtml

webtrifusion
sumber
3
+1 Saya mengalami masalah yang sama dan ini membantu menemukan solusinya. Ternyata saya memiliki [Bind (Kecualikan = "OrderID")] dalam model Pesanan saya yang menyebabkan nilai ID entitas menjadi nol pada HttpPost.
Knalpot
2
Itulah tepatnya yang saya lewatkan. ID objek saya adalah 0.
Azhar Khorasany
4
@ Html.HiddenFor (model => model.productID) - bekerja dengan sempurna. Saya kehilangan productID di EDIT HALAMAN (MVC RAZOR)
Ravi Ram
2
Saya memiliki masalah serupa tetapi dengan twist. Bagi saya masalahnya adalah saya tidak memiliki pengaturan tabel sql dengan benar. Bidang kunci utama saya tidak disetel ke kenaikan otomatis. Jadi EF akan mengirimkan catatan yang saya coba masukkan kunci w / oa yang baik-baik saja jika Anda ingat untuk memberi tahu sql bidang itu adalah bidang Identitas kenaikan otomatis, yang saya lupa: <
Agile Noob
1
Masalah yang sama tetapi menggunakan kunci komposit. Salah satu nilai kunci tidak ditetapkan.
obaylis
113

Wow, banyak jawaban, tetapi saya mendapatkan kesalahan ini ketika saya melakukan sesuatu yang sedikit berbeda yang tidak disebutkan oleh orang lain.

Singkatnya, jika Anda membuat objek baru dan memberi tahu EF bahwa itu dimodifikasi menggunakan EntityState.Modifiedmaka itu akan membuang kesalahan ini karena belum ada dalam database. Ini kode saya:

MyObject foo = new MyObject()
{
    someAttribute = someValue
};

context.Entry(foo).State = EntityState.Modified;
context.SaveChanges();

Ya, ini kelihatannya bodoh, tetapi ini muncul karena metode yang dulu digunakan foountuk itu telah dibuat sebelumnya, sekarang hanya someValuediteruskan dan diciptakan foosendiri.

Perbaikan mudah, cukup ubah EntityState.ModifiedkeEntityState.Added atau perubahan yang seluruh baris ke:

context.MyObject.Add(foo);
Ben
sumber
Terima kasih telah memposting ini. Itu masalah saya juga, saya telah menyalin-paste beberapa kode yang mengatur Negara ke EntityState.Modified.
clayRay
23

Saya menghadapi kesalahan menakutkan yang sama ... :) Kemudian saya menyadari bahwa saya lupa untuk mengatur a

@Html.HiddenFor(model => model.UserProfile.UserId)

untuk kunci utama objek yang diperbarui! Saya cenderung melupakan hal yang sederhana, tetapi sangat penting ini!

By the way: HiddenForadalah untuk ASP.NET MVC.

Leniel Maccaferri
sumber
3
Itu tampaknya seperti cacat keamanan, untuk menyimpan UserIddalam bentuk, sangat rentan terhadap peretas ... ini harus dihuni setelahnya dariHttpContext.Current.User.Identity.Name
Serj Sagan
@SerjSagan Anda benar ... tetapi selama Anda melakukan beberapa pemeriksaan di sisi server untuk mengonfirmasi UserId dan UserName saat ini, Anda baik untuk pergi.
Leniel Maccaferri
1
Maksud saya adalah mengapa bahkan menyimpan bahwa dalam HiddenForAnda harus mendapatkannya dari HttpContextanyways ... Saya tidak akan menempatkan properti ini dalam bentuk sama sekali, yang akan memaksa saya untuk selalu mengisi sisi server ...
Serj Sagan
16

Periksa apakah Anda lupa atribut "DataKeyNames" di GridView. itu adalah suatu keharusan ketika memodifikasi data dalam GridView

http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.datakeynames.aspx

Solly
sumber
+1. Solusi sempurna dan sederhana untuk saya. Saya mengikat GridView ke EntityDataSource dan tidak mengatur ini ke kunci utama saya pada objek.
Andez
Kita tahu bahwa Kendo UI tidak mendukung kunci komposit, tetapi jika saya menambahkan kolom baru yang menyatukan kunci saya menjadi satu, apa yang terjadi kemudian?
Branislav
15

Masalah ini disebabkan oleh salah satu dari dua hal: -

  1. Anda mencoba memperbarui satu baris dengan satu properti atau lebih Concurrency Mode: Fixed.. dan Optimistic Concurrency mencegah data disimpan. Yaitu. beberapa mengubah data baris antara saat Anda menerima data server dan ketika Anda menyimpan data server Anda.
  2. Anda mencoba memperbarui atau menghapus satu baris tetapi baris itu tidak ada. Contoh lain seseorang mengubah data (dalam hal ini, menghapus) di antara pengambilan lalu menyimpan ATAU Anda merasa datar kami mencoba memperbarui bidang yang bukan Identitas (mis. StoreGeneratedPattern = Computed) Dan baris itu tidak ada.
Murni
sumber
1
Ini juga bisa disebabkan jika semua properti objek yang ditugaskan, mereka ditugaskan dengan nilai yang sama seperti sebelumnya.
Serj Sagan
+1 untuk yang kedua. Saya telah StoreGeneratedPattern = Tidak Ada, berubah menjadi StoreGeneratedPattern = Identitas menyelesaikan masalah. Terima kasih
tkt986
12

Saya mendapat kesalahan yang sama ini karena bagian dari PK adalah kolom datetime, dan catatan yang dimasukkan menggunakan DateTime. Sekarang sebagai nilai untuk kolom itu. Kerangka kerja entitas akan memasukkan nilai dengan presisi milidetik, dan kemudian mencari nilai yang baru saja dimasukkan juga dengan presisi milidetik. Namun SqlServer telah membulatkan nilai ke presisi kedua, dan dengan demikian kerangka kerja tidak dapat menemukan nilai presisi milidetik.

Solusinya adalah memotong milidetik dari DateTime. Sekarang sebelum memasukkan.

innominate227
sumber
2
Kami memiliki masalah yang sama kecuali kami memasukkan ke dalam Datekolom dengan DateTimenilai
adam0101
1
Sama disini. Kami memiliki catatan gudang data dan menggunakan stempel waktu sebagai bagian dari kunci. Stempel waktu di gudang data adalah SQL DateTime, tetapi stempel waktu di C # tidak cocok. Saya mengubah tipe data SQL menjadi DateTime2 (7), memperbarui model EF, dan semuanya diperbaiki.
mmcfly
Mengubah kolom ke Datetime2 (7) bekerja untuk saya juga. Terima kasih @mmcfly
Dzejms
10

Saya mengalami masalah yang sama dan jawaban @ webtrifusion membantu menemukan solusinya.

Model saya menggunakan Bind(Exclude)atribut pada ID entitas yang menyebabkan nilai ID entitas menjadi nol pada HttpPost.

namespace OrderUp.Models
{
[Bind(Exclude = "OrderID")]
public class Order
{
    [ScaffoldColumn(false)]
    public int OrderID { get; set; }

    [ScaffoldColumn(false)]
    public System.DateTime OrderDate { get; set; }

    [Required(ErrorMessage = "Name is required")]
    public string Username { get; set; }
    }
}   
Knalpot
sumber
Masalah serupa, untuk alasan keamanan, saya memiliki Bind (termasuk = beberapa bidang). ID tidak ada dalam daftar. Saya juga menambahkannya sebagai input tersembunyi. Pasti telah menghapus sesuatu yang dihasilkan oleh MVC atau ID itu tidak ada sama sekali. Terima kasih untuk bantuannya.
MusicAndCode
10

Saya memiliki masalah yang sama, saya mencari tahu yang disebabkan oleh RowVersion yang nol. Periksa Anda Id dan Anda RowVersion yang tidak null .

untuk informasi lebih lanjut lihat tutorial ini

http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/handling-concurrency-w----ity-framework-in-an-asp-net-mvc-application

Bilel Chaouadi
sumber
versi baris tidak ada dalam kasus saya
Prakash
Dalam kasus saya, saya tidak sengaja menghapus bidang Id di [Bind (Include = properties)] saya. Tambahkan kembali dan itu berfungsi dengan baik.
Gua
8

Saya mulai mendapatkan kesalahan ini setelah berubah dari model-pertama ke kode-pertama. Saya memiliki beberapa utas memperbarui basis data di mana beberapa mungkin memperbarui baris yang sama. Saya tidak tahu mengapa saya tidak punya masalah menggunakan model-pertama, asumsikan bahwa ia menggunakan default konkurensi yang berbeda.

Untuk mengatasinya di satu tempat mengetahui kondisi di mana itu mungkin terjadi, saya menambahkan overload berikut ke kelas DbContext saya:

using System.Data.Entity.Core.Objects;
using System.Data.Entity.Infrastructure;

public class MyDbContext: DbContext {
...
        public int SaveChanges(bool refreshOnConcurrencyException, RefreshMode refreshMode = RefreshMode.ClientWins) {
            try {
                return SaveChanges();
            }
            catch (DbUpdateConcurrencyException ex) {
                foreach (DbEntityEntry entry in ex.Entries) {
                    if (refreshMode == RefreshMode.ClientWins)
                        entry.OriginalValues.SetValues(entry.GetDatabaseValues());
                    else
                        entry.Reload();
                }
                return SaveChanges();
            }
        }
}

Kemudian dipanggil SaveChanges(true) dimanapun berlaku.

terlebih lagi
sumber
1
OK, semua orang setuju tentang masalah ini, menunjukkan bagaimana mereka dapat memicu dll, tetapi jawaban ini memiliki jawaban yang keren. Saya menggunakan model lanjutkan pembaruan (tidak ada tombol simpan di sini, sayang) dan mendapatkan ini di pembaruan jaringan ketika utas EF tertinggal, dan menyelesaikannya. Cemerlang bekerja nama baik saya .. Anda membuat saya terlihat seperti pahlawan - berdiri di bahu raksasa !!
Tony Trembath-Drake
Membantu saya juga, lihat ini untuk lebih banyak opsi- stackoverflow.com/a/13891724/4836581
Zvi Redler
7

Anda harus secara eksplisit menyertakan BoundField dari kunci utama. Jika Anda tidak ingin pengguna melihat kunci utama, Anda harus menyembunyikannya melalui css:

    <asp:BoundField DataField="Id_primary_key" ItemStyle-CssClass="hidden" 
HeaderStyle-CssClass="hidden" />

Di mana 'hidden' adalah kelas dalam css yang tampilannya diatur ke 'tidak ada'.

Paulo
sumber
1
hah, Anda memberi saya petunjuk bahwa saya menghapus bidang id tersembunyi saya di ASP.NET MVC. Terima kasih @Paulo! :)
Tomasz Iniewicz
7

Saat mengedit, sertakan id atau kunci utama entitas sebagai bidang tersembunyi dalam tampilan

yaitu

      @Html.HiddenFor(m => m.Id)

yang memecahkan masalah.

Juga jika model Anda menyertakan item yang tidak digunakan juga termasuk itu dan mengirimkannya ke controller

Arun Aravind
sumber
7

Saya juga menemukan kesalahan ini. Masalahnya ternyata disebabkan oleh Pemicu di atas meja yang saya coba selamatkan. Trigger menggunakan 'INSTEAD OF INSERT' yang berarti 0 baris pernah dimasukkan ke tabel itu, karenanya kesalahan. Untungnya dalam kasus fungsi pemicu tidak benar, tapi saya kira itu bisa menjadi operasi yang valid yang entah bagaimana harus ditangani dalam kode. Semoga ini bisa membantu seseorang suatu hari.

Dosa
sumber
2
Entity dapat diperdaya untuk mempercayai bahwa baris ditambahkan dengan mengembalikan pernyataan SELECT (dengan kolom kunci utama) dari pelatuk.
jahu
1
Untuk memperluas komentar oleh @jahu, saya harus mendapatkan id aktual dari item yang baru saja dimasukkan untuk dikembalikan dari pemicu saya dan nama kolom harus cocok dengan kolom identitas tabel pemicu (dalam kasus saya, sebenarnya merupakan tampilan sehingga tidak jadi tidak memiliki identitasnya sendiri tetapi saya telah menipu edmx agar percaya bahwa itu memang benar). Pemicu saya sedang melakukan penyisipan ke tabel terpisah, jadi saya baru saja menambahkan baris terakhir ini ke pemicu saya:SELECT SCOPE_IDENTITY() as MyViewId
DannyMeister
Lihat juga pertanyaan ini: stackoverflow.com/questions/5820992/…
J. Polfer
Dalam kasus saya, saya melakukan operasi penghapusan pada entitas dalam koleksi anak tetapi ada pemicu pada penghapusan untuk salah satu entitas anak yang menyebabkan entitas anak lainnya dihapus. Ini menyebabkan kesalahan karena baris N - 1 terpengaruh karena pemicu menghapus salah satu entitas anak itu sendiri sebelum kerangka kerja entitas mencoba menghapusnya.
skeletank
6

Saya menemukan masalah ini pada tabel yang tidak memiliki kunci utama dan memiliki kolom DATETIME (2, 3) (jadi "kunci utama" entitas adalah kombinasi dari semua kolom) ... Saat melakukan penyisipan timestamp memiliki waktu yang lebih tepat (2018-03-20 08: 29: 51.8319154) yang terpotong menjadi (2018-03-20 08: 29: 51.832) sehingga pencarian pada bidang kunci gagal.

combatc2
sumber
5

Saya juga mengalami kesalahan ini. Ada beberapa situasi di mana Entitas mungkin tidak menyadari Konteks Database aktual yang Anda gunakan atau Model mungkin berbeda. Untuk ini, set: EntityState.Modified; untuk EntityState. Ditambahkan;

Untuk melakukan ini:

if (ModelState.IsValid)
{
context.Entry(yourModelReference).State = EntityState.Added;
context.SaveChanges();
}

Ini akan memastikan Entitas tahu Anda menggunakan atau menambahkan Negara tempat Anda bekerja. Pada titik ini semua Nilai Model yang benar harus ditetapkan. Berhati-hatilah untuk tidak kehilangan perubahan apa pun yang mungkin telah dibuat di latar belakang.

Semoga ini membantu.

paku berkarat
sumber
1
Anda seorang gurú! ini bekerja untuk saya!
Hernaldo Gonzalez
5
  @Html.HiddenFor(model => model.RowVersion)

Versi baris saya adalah nol, jadi harus menambahkan ini ke tampilan yang memecahkan masalah saya

Prakash
sumber
Tidak melewatkan RowVersion dari View ke Action edit, ditambah saya lupa melakukan model yang mengikat RowVersion. Pada saat Anda menyimpan objek ke db, Anda memerlukan nilai RowVersion sebelumnya dikirimkan ke db bersama dengan objek untuk cek concurrency. Anda membuat kesalahan konyol ketika Anda membutuhkan sesuatu dengan lebih cepat!
Dhanuka777
5

Garis [DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None)]melakukan trik dalam kasus saya:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;


[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int? SomeNumber { get; set; }
Tomo
sumber
4

Pastikan saja tabel dan formulir keduanya memiliki kunci utama dan edmx diperbarui.

saya menemukan bahwa setiap kesalahan selama pembaruan biasanya karena: - Tidak ada kunci utama dalam Tabel - Tidak ada kunci utama dalam Edit tampilan / formulir (misalnya @Html.HiddenFor(m=>m.Id)

Moji
sumber
4

Saya memiliki masalah yang sama. Dalam kasus saya, saya mencoba memperbarui kunci utama, yang tidak diizinkan.

ajaysinghdav10d
sumber
4

Saya mendapatkan kesalahan ini secara sporadis saat menggunakan async metode. Belum terjadi sejak saya beralih ke metode sinkron.

Kesalahan secara sporadis:

[Authorize(Roles = "Admin")]
[HttpDelete]
[Route("file/{id}/{customerId}/")]
public async Task<IHttpActionResult> Delete(int id, int customerId)
{
    var file = new Models.File() { Id = id, CustomerId = customerId };
    db.Files.Attach(file);
    db.Files.Remove(file);

    await db.SaveChangesAsync();

    return Ok();
}

Bekerja sepanjang waktu:

[Authorize(Roles = "Admin")]
[HttpDelete]
[Route("file/{id}/{customerId}/")]
public IHttpActionResult Delete(int id, int customerId)
{
    var file = new Models.File() { Id = id, CustomerId = customerId };
    db.Files.Attach(file);
    db.Files.Remove(file);

    db.SaveChanges();

    return Ok();
}
Ogglas
sumber
Meskipun ini menyelesaikan masalah saya, itu berfungsi untuk menunjukkan masalah mendasar yang disebutkan sebelumnya dalam posting ini tentang versi PK & Row. Saya telah lupa untuk menambahkan peta skema untuk tabel baru yang lebih rumit oleh fakta bahwa PK tidak mengikuti aturan konvensi penamaan. <Nama Tabel> ID.
midohioboarder
3

Saya mendapatkan kesalahan itu ketika saya menghapus beberapa baris dalam DB (dalam loop), dan menambahkan yang baru di tabel yang sama.

Solusi bagi saya adalah, secara dinamis membuat konteks baru di setiap iterasi loop

Tony
sumber
Saya harus melakukan hal yang sama, masih tidak yakin mengapa masalah terjadi pada awalnya, tetapi ini berhasil.
Jed Grant
3
    public void Save(object entity)
    {
        using (var transaction = Connection.BeginTransaction())
        {
        try
                {
                    SaveChanges();
                    transaction.Commit();
                }
                catch (OptimisticConcurrencyException)
                {
                    if (ObjectStateManager.GetObjectStateEntry(entity).State == EntityState.Deleted || ObjectStateManager.GetObjectStateEntry(entity).State == EntityState.Modified)
                        this.Refresh(RefreshMode.StoreWins, entity);
                    else if (ObjectStateManager.GetObjectStateEntry(entity).State == EntityState.Added)
                        Detach(entity);
                    AcceptAllChanges(); 
                    transaction.Commit();
                }
        }
    }
Prem Prakash
sumber
Bisakah Anda jelaskan apa yang dimaksud dengan 'ini' di sini dan apa itu ObjectStateManager? Saya mencoba ini di kelas repositori dasar kami tetapi mendapatkan kesalahan
Naomi
3

Ini juga akan terjadi jika Anda mencoba memasukkan ke dalam situasi kendala yang unik, yaitu jika Anda hanya dapat memiliki satu jenis alamat per majikan dan Anda mencoba memasukkan yang kedua dari jenis yang sama dengan majikan yang sama, Anda akan mendapatkan masalah yang sama .

ATAU

Ini juga bisa terjadi jika semua properti objek yang ditugaskan, mereka ditugaskan dengan nilai yang sama seperti sebelumnya.

        using(var db = new MyContext())
        {
            var address = db.Addresses.FirstOrDefault(x => x.Id == Id);

            address.StreetAddress = StreetAddress; // if you are assigning   
            address.City = City;                   // all of the same values
            address.State = State;                 // as they are
            address.ZipCode = ZipCode;             // in the database    

            db.SaveChanges();           // Then this will throw that exception
        }
Serj Sagan
sumber
2

Jika Anda mencoba membuat pemetaan di file edmx ke "fungsi Impor", ini dapat menyebabkan kesalahan ini. Cukup kosongkan bidang untuk disisipkan, perbarui dan hapus yang terletak di Rincian Pemetaan untuk entitas tertentu di edmx Anda, dan itu akan berfungsi. Saya harap saya membuatnya jelas.

Mubarak
sumber
2

Saya mendapat pengecualian ini ketika melampirkan objek yang tidak ada di database. Saya mengasumsikan objek dimuat dari konteks yang terpisah, tetapi jika itu adalah pertama kalinya pengguna mengunjungi situs, objek tersebut dibuat dari awal. Kami memiliki kunci primer yang bertambah secara otomatis, jadi saya bisa menggantinya

context.Users.Attach(orderer);

dengan

if (orderer.Id > 0) {
    context.Users.Attach(orderer);
}
Andrew
sumber
2

Yah saya punya masalah yang sama. Tapi ini karena kesalahan saya sendiri. Sebenarnya saya menyimpan suatu objek alih-alih menambahkannya. Jadi ini konfliknya.

Ali
sumber
2

Salah satu cara untuk men-debug masalah ini dalam lingkungan Sql Server adalah dengan menggunakan Sql Profiler yang disertakan dengan salinan SqlServer Anda, atau jika menggunakan versi Express, dapatkan salinan Expresser Profileer secara gratis dari CodePlex dengan mengikuti tautan di bawah ini:

Profiler Ekspres

Dengan menggunakan Sql Profiler Anda bisa mendapatkan akses ke apa pun yang dikirim oleh EF ke DB. Dalam kasus saya ini berjumlah:

exec sp_executesql N'UPDATE [dbo].[Category]
SET [ParentID] = @0, [1048] = NULL, [1033] = @1, [MemberID] = @2, [AddedOn] = @3
WHERE ([CategoryID] = @4)
',N'@0 uniqueidentifier,@1 nvarchar(50),@2 uniqueidentifier,@3 datetime2(7),@4 uniqueidentifier',
@0='E060F2CA-433A-46A7-86BD-80CD165F5023',@1=N'I-Like-Noodles-Do-You',@2='EEDF2C83-2123-4B1C-BF8D-BE2D2FA26D09',
@3='2014-01-29 15:30:27.0435565',@4='3410FD1E-1C76-4D71-B08E-73849838F778'
go

Saya menyalin ini ke jendela permintaan di Sql Server dan menjalankannya. Cukup yakin, meskipun berjalan, 0 rekaman dipengaruhi oleh kueri ini sehingga kesalahan dikembalikan oleh EF.

Dalam kasus saya, masalahnya disebabkan oleh CategoryID.

Tidak ada CategoryID diidentifikasi oleh ID EF dikirim ke database sehingga 0 catatan terpengaruh.

Ini bukan kesalahan EF, tapi bukan buggy null yang menyatu "??" pernyataan di View Controller yang mengirim omong kosong ke tier data.

rism
sumber
2

Tidak satu pun dari jawaban di atas yang cukup menutupi situasi saya dan solusi untuk itu.

Kode tempat kesalahan dilemparkan ke controller MVC5:

        if (ModelState.IsValid)
        {
            db.Entry(object).State = EntityState.Modified; 
            db.SaveChanges(); // line that threw exception
            return RedirectToAction("Index");
        }

Saya menerima pengecualian ini ketika saya menyimpan objek dari tampilan Edit. Alasan itu melemparkannya adalah karena ketika saya kembali untuk menyimpannya, saya telah memodifikasi properti yang membentuk kunci utama pada objek. Jadi, mengatur statusnya ke Dimodifikasi tidak masuk akal untuk EF - itu adalah entri baru, bukan entri yang disimpan sebelumnya.

Anda dapat menyelesaikan ini dengan A) memodifikasi panggilan simpan ke Tambahkan objek, atau B) hanya tidak mengubah kunci utama pada edit. Saya melakukan B).

J. Polfer
sumber
2

Ketika jawaban yang diterima mengatakan " itu tidak akan berakhir menimpa perubahan yang aplikasi Anda tidak tahu telah terjadi ", saya ragu karena objek saya baru saja dibuat. Tapi kemudian ternyata, ada INSTEAD OF UPDATE, INSERT- TRIGGERlampiran pada tabel yang memperbarui kolom terhitung dari tabel yang sama.

Setelah saya mengubah ini AFTER INSERT, UPDATE, itu berfungsi dengan baik.

Mahesh
sumber
2

Ini terjadi pada saya karena ketidakcocokan antara datetime dan datetime2. Anehnya, itu bekerja dengan baik sebelum penguji menemukan masalah. Model Kode Pertama Saya menyertakan DateTime sebagai bagian dari kunci utama:

[Key, Column(Order = 2)]  
public DateTime PurchasedDate { get; set; } = (DateTime)SqlDateTime.MinValue;

Kolom yang dihasilkan adalah kolom datetime. Saat memanggil SaveChanges, EF menghasilkan SQL berikut:

-- Region Parameters
DECLARE @0 Int = 2
DECLARE @1 Int = 25
DECLARE @2 Int = 141051
DECLARE @3 DateTime2 = '2017-07-27 15:16:09.2630000' --(will not equal a datetime value)
-- EndRegion
UPDATE [dbo].[OrganizationSurvey]
SET [OrganizationSurveyStatusId] = @0
WHERE ((([SurveyID] = @1) AND ([OrganizationID] = @2)) AND ([PurchasedDate] = @3))

Karena berusaha mencocokkan kolom datetime dengan nilai datetime2, hasilnya tidak ada. Satu-satunya solusi yang dapat saya pikirkan adalah mengubah kolom menjadi datetime2:

[Key, Column(Order = 2, TypeName = "DateTime2")]  
public DateTime PurchasedDate { get; set; } = (DateTime)SqlDateTime.MinValue;
R. Salisbury
sumber
1
Keanehan vs bekerja tidak bekerja hubungannya dengan mendasari Format / dasar datetimevs datetime2. Pada dasarnya beberapa nilai milidetik akan mengevaluasi kecocokan, yang lain tidak. Hal yang sama terjadi pada saya dan saya juga beralih ke DateTime2.
xr280xr
+1 Saya berharap saya dapat memberi +1 pada yang satu ini untuk Anda. Saya setelah meneliti banyak tempat saya akhirnya menemukan ini dan menyadari bahwa, memang, saya memiliki Datetime sebagai bagian dari kunci utama saya. Ya, ini memang memperbaikinya. Saya memperbarui kolom ke Datetime2 dan itu berhasil. Sekarang, daging sapi saya dengan Entity Framework untuk merancang permintaan yang jelek untuk ini yang memaksa saya untuk melakukan ini.
Catchops