Entity Framework: “L’aggiornamento dell’archivio, l’inserimento o l’istruzione di eliminazione hanno interessato un numero imprevisto di righe (0).”

Sto usando Entity Framework per popolare un controllo di griglia. A volte quando faccio aggiornamenti ottengo il seguente errore:

L’aggiornamento dell’archivio, l’inserimento o l’eliminazione dell’archivio hanno interessato un numero imprevisto di righe (0). Le entity framework potrebbero essere state modificate o eliminate da quando le entity framework sono state caricate. Aggiorna le voci di ObjectStateManager.

Non riesco a capire come riprodurre questo. Ma potrebbe avere qualcosa a che fare con quanto sono vicini gli aggiornamenti. Qualcuno ha visto questo o qualcuno sa a cosa si riferisce il messaggio di errore?

Edit: Purtroppo non sono più libero di riprodurre il problema che avevo qui, perché mi sono allontanato da questo progetto e non ricordo se alla fine ho trovato una soluzione, se un altro sviluppatore l’ha sistemata, o se ci ho lavorato intorno. Pertanto non posso accettare alcuna risposta.

Questo è un effetto collaterale di una funzionalità chiamata concorrenza ottimistica.

Non è sicuro al 100% come triggersrlo / distriggersrlo in Entity Framework, ma in pratica quello che ti dice è che tra quando hai estratto i dati dal database e quando hai salvato le tue modifiche qualcun altro ha cambiato i dati (il che significa che quando sei andato per salvarlo 0 righe effettivamente aggiornate). In termini SQL, la clausola where della query di update contiene il valore originale di ogni campo nella riga e, se sono interessate le righe 0, sa che qualcosa è andato storto.

L’idea alla base è che non finirai per sovrascrivere un cambiamento che la tua applicazione non sapeva che è successo – è fondamentalmente un piccolo provvedimento di sicurezza lanciato da .NET su tutti gli aggiornamenti.

Se è coerente, le probabilità stanno accadendo all’interno della tua logica (EG: In realtà stai aggiornando i dati tu stesso in un altro metodo tra la selezione e l’aggiornamento), ma potrebbe essere semplicemente una condizione di competizione tra due applicazioni.

Mi sono imbattuto in questo ed è stato causato dal campo ID (chiave) dell’ quadro non impostato. Pertanto, quando il contesto è andato a salvare i dati, non è stato ansible trovare un ID = 0. Assicurarsi di inserire un punto di interruzione nell’istruzione di aggiornamento e verificare che l’ID dell’ quadro sia stato impostato.

Dal commento di Paul Bellora

Ho avuto questo problema esatto, causato dimenticando di includere l’input dell’ID nascosto nella pagina di modifica .cshtml

Wow, molte risposte, ma ho ricevuto questo errore quando ho fatto qualcosa di leggermente diverso che nessun altro ha menzionato.

Per EntityState.Modified breve, se si crea un nuovo object e si comunica a EF che è stato modificato utilizzando EntityState.Modified , verrà generato questo errore poiché non esiste ancora nel database. Ecco il mio codice:

 MyObject foo = new MyObject() { someAttribute = someValue }; context.Entry(foo).State = EntityState.Modified; context.SaveChanges(); 

Sì, questo sembra sciocco, ma è sorto perché il metodo in questione usato per someValue è stato creato in precedenza, ora ha solo someValue passato e crea lo stesso foo .

Correzione facile, basta modificare EntityState.Modified in EntityState.Added o modificare l’intera riga in:

 context.MyObject.Add(foo); 

Stavo affrontando questo stesso errore spaventoso … 🙂 Poi ho capito che mi stavo dimenticando di impostare un

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

per la chiave primaria dell’object che si sta aggiornando! Tendo a dimenticare questo semplice, ma molto importante!

A proposito: HiddenFor è per ASP.NET MVC.

Controlla se hai dimenticato l’attributo “DataKeyNames” in GridView. è un must quando si modificano i dati all’interno di GridView

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

Il problema è causato da una di queste due cose:

  1. Si è tentato di aggiornare una riga con una o più proprietà in Concurrency Mode: Fixed .. e la Concorrenza ottimistica ha impedito il salvataggio dei dati. Vale a dire. alcuni hanno cambiato i dati delle righe tra il momento in cui hai ricevuto i dati del server e quando hai salvato i dati del tuo server.
  2. Hai provato ad aggiornare o eliminare una riga ma la riga non esiste. Un altro esempio di qualcuno che modifica i dati (in questo caso, rimuovendo) tra un recupero e poi risparmi O stai pianamente cercando di aggiornare un campo che non è StoreGeneratedPattern = Computed (cioè StoreGeneratedPattern = Computed ) e quella riga non esiste .

Stavo avendo lo stesso problema e la risposta di @ webtrifusion ha aiutato a trovare la soluzione.

Il mio modello utilizzava l’attributo Bind(Exclude) sull’ID dell’entity framework che stava causando il valore dell’ID dell’ quadro su zero su 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; } } } 

Ho ricevuto lo stesso errore perché una parte del PK era una colonna datetime e il record inserito utilizzava DateTime.Ora come valore per quella colonna. Il framework Entity inserirà il valore con precisione millisecondo, quindi cercherà il valore appena inserito anche con una precisione millisecondo. Tuttavia, SqlServer aveva arrotondato il valore alla seconda precisione e quindi il framework di entity framework non era in grado di trovare il valore di precisione in millisecondi.

La soluzione era di troncare i millisecondi da DateTime.Ora prima dell’inserimento.

Ho avuto lo stesso problema, ho scoperto che era causato da RowVersion che era nullo. Verifica che il tuo ID e la tua RowVersion non siano nulli .

per ulteriori informazioni, fare riferimento a questo tutorial

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

Mentre la modifica include l’id o la chiave primaria dell’ quadro come campo nascosto nella vista

vale a dire

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

questo risolve il problema

Inoltre, se il tuo modello include elementi non utilizzati, includi anche quello e pubblicalo sul controller

È necessario includere esplicitamente un BoundField della chiave primaria. Se non vuoi che l’utente veda la chiave primaria, devi nasconderlo tramite css:

   

Dove ‘hidden’ è una class in css che ha la sua visualizzazione impostata su ‘none’.

Ho anche trovato questo errore. Il problema è stato causato da un trigger sul tavolo che stavo cercando di salvare. Il Trigger ha usato “INSTEAD OF INSERT” che significa che 0 righe sono mai state inserite in quella tabella, quindi l’errore. Fortunatamente nel maggio la funzionalità del trigger non era corretta, ma immagino che potrebbe essere un’operazione valida che dovrebbe in qualche modo essere gestita nel codice. Spero che questo aiuti qualcuno un giorno.

Ho iniziato a ricevere questo errore dopo aver cambiato da modello prima a codice prima. Ho più thread che aggiornano un database in cui alcuni potrebbero aggiornare la stessa riga. Non so perché non ho avuto problemi con l’uso del model-first, suppongo che usi un default di concorrenza diverso.

Per gestirlo in un unico posto conoscendo le condizioni in cui si sarebbe verificato, ho aggiunto il seguente overload alla mia class DbContext:

 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(); } } } 

Quindi chiamato SaveChanges(true) ove applicabile.

  @Html.HiddenFor(model => model.RowVersion) 

Il mio rowversion era nullo, quindi ho dovuto aggiungere questo alla vista che ha risolto il mio problema

La linea [DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None)] fatto il trucco nel mio caso:

 using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; [Key] [DatabaseGenerated(DatabaseGeneratedOption.None)] public int? SomeNumber { get; set; } 

Assicurati che la tabella e il modulo abbiano entrambi la chiave primaria ed edmx aggiornati.

ho scoperto che gli errori durante l’aggiornamento erano solitamente dovuti a: – Nessuna chiave primaria nella tabella – Nessuna chiave primaria nella vista / forma Modifica (ad esempio @Html.HiddenFor(m=>m.Id )

Ho ricevuto questo errore sporadicamente quando utilizzo un metodo async . Non è successo da quando sono passato a un metodo sincrono.

Errori sporadici:

 [Authorize(Roles = "Admin")] [HttpDelete] [Route("file/{id}/{customerId}/")] public async Task 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(); } 

Funziona tutto il tempo:

 [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(); } 

Ho ricevuto questo errore quando stavo cancellando alcune righe nel DB (nel loop) e aggiungendo i nuovi nella stessa tabella.

Le soluzioni per me erano, per creare dynamicmente un nuovo contesto in ogni iterazione del ciclo

  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(); } } } 

Ho avuto lo stesso problema. Nel mio caso stavo cercando di aggiornare la chiave primaria, che non è consentita.

Se si sta tentando di creare il mapping nel file edmx in una “funzione Imports”, ciò può causare questo errore. Basta cancellare i campi per inserire, aggiornare ed eliminare che si trova in Dettagli di mapping per una determinata quadro in edmx, e dovrebbe funzionare. Spero di averlo chiarito.

Ho anche avuto questo errore. Ci sono alcune situazioni in cui l’Entità potrebbe non essere a conoscenza del contesto del database che stai utilizzando o del modello potrebbe essere diverso. Per questo, impostare: EntityState.Modified; a EntityState.Added;

Per fare questo:

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

Ciò garantirà che l’Entità sappia che stai usando o aggiungendo lo Stato con cui lavori. A questo punto è necessario impostare tutti i valori di modello corretti. Attento a non perdere le modifiche che potrebbero essere state apportate in background.

Spero che questo ti aiuti.

Ciò si verifica anche se si sta tentando di inserire in una situazione di vincolo univoco, cioè se si può avere solo un tipo di indirizzo per datore di lavoro e si tenta di inserire un secondo dello stesso tipo con lo stesso datore di lavoro, si otterrà lo stesso problema .

O

Questo potrebbe accadere anche se tutte le proprietà dell’object che sono state assegnate, sono state assegnate con gli stessi valori di prima.

  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 } 

Bene, ho lo stesso problema. Ma questo era dovuto al mio errore. In realtà stavo salvando un object invece di aggiungerlo. Quindi questo era il conflitto.

Un modo per eseguire il debug di questo problema in un ambiente Sql Server consiste nell’utilizzare Sql Profiler incluso nella copia di SqlServer oppure, se si utilizza la versione Express, ottenere gratuitamente una copia di Express Profiler da CodePlex dal seguente collegamento:

Express Profiler

Usando Sql Profiler puoi accedere a qualsiasi cosa venga inviata da EF al DB. Nel mio caso questo ammontava a:

 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 

Ho copiato questo in una finestra di query in Sql Server e l’ho eseguito. Abbastanza sicuro, anche se è stato eseguito, 0 record sono stati interessati da questa query, quindi l’errore viene restituito da EF.

Nel mio caso il problema è stato causato dal CategoryID.

Non vi è stato alcun ID di categoria identificato dall’ID EF inviato al database, quindi sono stati rilevati 0 record.

Questa non è stata la colpa di EF, ma piuttosto un bacato null “buggy” dichiarazione in un controller di visualizzazione che inviava assurdità fino al livello dati.

Nessuna delle risposte precedenti ha coperto abbastanza la mia situazione e la soluzione ad essa.

Codice in cui è stato generato l’errore nel controller MVC5:

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

Ho ricevuto questa eccezione quando stavo salvando un object da una vista Modifica. Il motivo per cui lo ha gettato era perché quando sono tornato a salvarlo, avevo modificato le proprietà che formavano la chiave primaria sull’object. Quindi, impostare il suo stato su Modified non aveva alcun senso per EF: era una nuova entrata, non una precedentemente salvata.

Puoi risolvere questo problema con A) modificando la chiamata di salvataggio su Aggiungi l’object o B), ma non modificare la chiave primaria in modifica. Ho fatto B).

Mi sono imbattuto in questo problema su un tavolo che mancava una chiave primaria e aveva una colonna DATETIME (2, 3) (quindi la “chiave primaria” dell’ quadro era una combinazione di tutte le colonne) … Quando si eseguiva l’inserimento il timestamp era un tempo più preciso (2018-03-20 08: 29: 51.8319154) che è stato troncato a (2018-03-20 08: 29: 51.832), pertanto la ricerca sui campi chiave non riesce.

Mi sono imbattuto in questo utilizzando RadGrid di Telerik. Ho avuto la chiave primaria come una colonna gridbound che era impostata in sola lettura. Funzionerebbe bene se la colonna fosse display = “false” ma readonly = “true” ha causato il problema. Ho risolto il problema visualizzando la colonna gridbound = false e aggiungendo una colonna template separata per la visualizzazione

        

Ho ottenuto questa eccezione durante il collegamento di un object che non esisteva nel database. Avevo pensato che l’object fosse caricato da un contesto separato, ma se era la prima volta che l’utente visita il sito, l’object è stato creato da zero. Abbiamo le chiavi primarie autoincrementanti, quindi posso sostituire

 context.Users.Attach(orderer); 

con

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

Questo può accadere se si tenta di aggiornare un record con un ID che non esiste nel database.