ventajas framework first example español desventajas code entity-framework

first - Entity Framework: "La actualización de la tienda, insertar o eliminar una declaración afectó un número inesperado de filas(0)".



entity framework nuget (30)

Estoy utilizando Entity Framework para rellenar un control de cuadrícula. A veces cuando hago actualizaciones me sale el siguiente error:

La actualización de la tienda, insertar o eliminar una declaración afectó un número inesperado de filas (0). Las entidades pueden haber sido modificadas o eliminadas desde que se cargaron las entidades. Actualizar las entradas de ObjectStateManager.

No puedo averiguar cómo reproducir esto. Pero podría tener algo que ver con lo cerca que hago las actualizaciones. ¿Alguien ha visto esto o alguien sabe a qué se refiere el mensaje de error?

Edit: Desafortunadamente, ya no estoy en libertad de reproducir el problema que estaba teniendo aquí, porque me alejé de este proyecto y no recuerdo si finalmente encontré una solución, si otro desarrollador la solucionó o si trabajé en ella. Por lo tanto no puedo aceptar ninguna respuesta.


Bueno tengo este mismo problema. Pero esto se debió a mi propio error. En realidad estaba guardando un objeto en lugar de agregarlo. Así que este fue el conflicto.


Comencé a recibir este error después de cambiar de modelo primero a código primero. Tengo varios subprocesos que actualizan una base de datos donde algunos pueden actualizar la misma fila. No sé por qué no tuve un problema al usar el modelo primero, asumiendo que usa un valor predeterminado de concurrencia diferente.

Para manejarlo en un solo lugar sabiendo las condiciones bajo las cuales podría ocurrir, agregué la siguiente sobrecarga a mi clase 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(); } } }

Luego se llama SaveChanges(true) donde sea aplicable.



Cuando la respuesta aceptada decía " no terminará sobrescribiendo un cambio que su aplicación no sabía que había ocurrido ", fui escéptico porque mi objeto fue creado recientemente. Pero luego resulta que había un INSTEAD OF UPDATE, INSERT- TRIGGER adjunto a la tabla que estaba actualizando una columna calculada de la misma tabla.

Una vez que cambié esto a AFTER INSERT, UPDATE , AFTER INSERT, UPDATE bien.


Debe incluir explícitamente un BoundField de la clave principal. Si no desea que el usuario vea la clave principal, debe ocultarla a través de css:

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

Donde ''oculto'' es una clase en css que tiene su pantalla configurada en ''ninguna''.


Durante la edición, incluya el ID o la clave principal de la entidad como un campo oculto en la vista

es decir

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

Eso resuelve el problema.

Además, si su modelo incluye un elemento no utilizado, también incluya eso y publíquelo en el controlador


El problema es causado por una de estas dos cosas:

  1. Intentó actualizar una fila con una o más propiedades Concurrency Mode: Fixed ... y la concurrencia optimista evitó que se guardaran los datos. Es decir. algunos cambiaron los datos de la fila entre el momento en que recibió los datos del servidor y cuando guardó los datos de su servidor.
  2. Intentó actualizar o eliminar una fila pero la fila no existe. Otro ejemplo de alguien que está cambiando los datos (en este caso, eliminando) entre una recuperación y luego guardar O NO puede intentar actualizar un campo que no es una Identidad (es decir, StoreGeneratedPattern = Computed ) y esa fila no existe .

Encontré este problema en una tabla en la que faltaba una clave principal y tenía una columna DATETIME (2, 3) (por lo que la "clave principal" de la entidad era una combinación de todas las columnas) ... Al realizar la inserción, la marca de tiempo tenía una hora más precisa (2018-03-20 08: 29: 51.8319154) que se truncó a (2018-03-20 08: 29: 51.832), por lo que la búsqueda en los campos clave falla.


Eso es un efecto secundario de una característica llamada concurrencia optimista.

No estoy 100% seguro de cómo activarlo / desactivarlo en Entity Framework, pero básicamente lo que le está diciendo es que entre cuando sacó los datos de la base de datos y cuando guardó los cambios, otra persona ha cambiado los datos (lo que significaba cuando fue para guardarlo 0 filas realmente se actualizaron). En términos de SQL, su consulta de update , where cláusula contiene el valor original de cada campo en la fila, y si 0 filas se ven afectadas, sabe que algo salió mal.

La idea detrás de esto es que no terminará sobrescribiendo un cambio que su aplicación no sabía que sucedió, es básicamente una pequeña medida de seguridad lanzada por .NET en todas sus actualizaciones.

Si es coherente, es probable que ocurra dentro de su propia lógica (por ejemplo: en realidad, usted mismo está actualizando los datos en otro método entre la selección y la actualización), pero podría ser simplemente una condición de competencia entre dos aplicaciones.


Estaba teniendo el mismo problema y la answer @ webtrifusion ayudó a encontrar la solución.

Mi modelo estaba usando el atributo Bind(Exclude) en la ID de la entidad que causaba que el valor de la ID de la entidad fuera cero en 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; } } }


Esto también sucederá si intenta insertarse en una situación de restricción única, es decir, si solo puede tener un tipo de dirección por empleador e intenta insertar un segundo de ese mismo tipo con el mismo empleador, tendrá el mismo problema .

O

Esto también podría suceder si todas las propiedades de objeto que se asignaron a ellos, se asignaron con los mismos valores que tenían antes.

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 }


La línea [DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None)] hizo el truco en mi caso:

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


Me encontré con esto utilizando RadGrid de Telerik. Tenía la clave principal como una columna cuadriculada que estaba configurada para solo lectura. Funcionaría bien si la columna fuera display = "false" pero readonly = "true" causó el problema. Lo resolví haciendo que la columna cuadriculada se muestre = falso y agregue una columna de plantilla separada para mostrar

<telerik:GridBoundColumn HeaderText="Shouldnt see" Display="false" UniqueName="Id" DataField="Id"> </telerik:GridBoundColumn> <telerik:GridTemplateColumn HeaderText="Id" UniqueName="IdDisplay"> <ItemTemplate> <asp:Label ID="IDLabel" runat="server" Text=''<%# Eval("Id") %>''></asp:Label> </ItemTemplate> </telerik:GridTemplateColumn>


Me encontré con esto y fue causado por el campo de ID (clave) de la entidad que no se configuró. Por lo tanto, cuando el contexto fue a guardar los datos, no pudo encontrar una ID = 0. Asegúrese de colocar un punto de ruptura en su estado de actualización y verificar que se haya establecido la ID de la entidad.

Del comentario de Paul Bellora.

Tuve este problema exacto, causado por olvidarme de incluir la entrada de ID oculta en la página de edición .cshtml


Me enfrentaba a este mismo error de miedo ... :) Entonces me di cuenta de que me había olvidado de configurar un

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

para la clave primaria del objeto que se actualiza! Tiendo a olvidar esta cosa simple, pero muy importante!

Por cierto: HiddenFor es para ASP.NET MVC.


Ninguna de las respuestas anteriores cubrió mi situación y la solución.

Código donde se produjo el error en el controlador MVC5:

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

Recibí esta excepción cuando estaba guardando un objeto en una vista Editar. La razón por la que lo arrojó fue porque cuando volví a guardarlo, había modificado las propiedades que formaban la clave principal en el objeto. Por lo tanto, establecer su estado en Modificado no tenía ningún sentido para EF: era una nueva entrada, no una guardada previamente.

Puede resolver esto ya sea A) modificando la llamada guardada para agregar el objeto, o B) simplemente no cambie la clave principal en la edición. Yo hice B).


Obtuve esta excepción al adjuntar un objeto que no existía en la base de datos. Supuse que el objeto se cargó desde un contexto diferente, pero si era la primera vez que el usuario visitaba el sitio, el objeto se creó desde cero. Tenemos claves primarias de incremento automático, por lo que podría reemplazar

context.Users.Attach(orderer);

con

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


Obtuve este mismo error porque parte de la PK era una columna de fecha y hora y el registro que se inserta utiliza DateTime. Ahora como el valor de esa columna. Entity framework insertaría el valor con una precisión de milisegundos y luego buscaría el valor que acaba de insertar también con una precisión de milisegundos. Sin embargo, SqlServer había redondeado el valor a una segunda precisión y, por lo tanto, el marco de la entidad no pudo encontrar el valor de precisión en milisegundos.

La solución fue truncar los milisegundos de DateTime. Ahora antes de insertar.


Recibí ese error cuando estaba eliminando algunas filas en la base de datos (en el bucle), y agregando las nuevas en la misma tabla.

Las soluciones para mí fueron, crear dinámicamente un nuevo contexto en cada iteración de bucle.


Recibí este error esporádicamente al usar un método async . No ha sucedido desde que cambié a un método síncrono.

Esporádicamente los errores:

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

Funciona todo el tiempo:

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


Si está intentando crear una asignación en su archivo edmx a una "función Importaciones", esto puede provocar este error. Simplemente borre los campos para insertar, actualizar y eliminar que se encuentran en Detalles de asignación para una entidad determinada en su edmx, y debería funcionar. Espero haberlo dejado claro.


También me encontré con este error. El problema que resultó fue causado por un disparador en la mesa que estaba tratando de guardar. El activador utilizó ''INSTEAD OF INSERT'', lo que significa que se han insertado 0 filas en esa tabla, de ahí el error. Afortunadamente, en el caso de que la funcionalidad de disparo fuera incorrecta, supongo que podría ser una operación válida que de alguna manera debería manejarse en código. Espero que esto ayude a alguien algún día.


También tuve este error. Hay algunas situaciones en las que la Entidad puede no estar al tanto del contexto de la base de datos real que está utilizando o el Modelo puede ser diferente. Para esto, establece: EntityState.Modified; a EntityState.Added;

Para hacer esto:

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

Esto asegurará que la Entidad sepa que está usando o agregando el Estado con el que está trabajando. En este punto, se deben configurar todos los valores de modelo correctos. Tenga cuidado de no perder ningún cambio que se haya hecho en el fondo.

Espero que esto ayude.



Una forma de depurar este problema en un entorno de Sql Server es usar el Sql Profiler incluido con su copia de SqlServer, o si usa la versión Express, obtenga una copia de Express Profiler gratis desde CodePlex mediante el siguiente enlace:

Express Profiler

Al usar Sql Profiler puede obtener acceso a lo que sea enviado por EF a la base de datos. En mi caso esto equivalía 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

Copié y pegué esto en una ventana de consulta en el servidor SQL y lo ejecuté. Por supuesto, aunque se ejecutó, 0 registros se vieron afectados por esta consulta, por lo tanto, EF devolvió el error.

En mi caso, el problema fue causado por el CategoryID.

No se identificó un ID de categoría por el ID EF enviado a la base de datos, por lo que se vieron afectados 0 registros.

Sin embargo, esto no fue culpa de EF, sino más bien un null con errores "?" Estado de cuenta en un controlador de vista que estaba enviando sin sentido al nivel de datos.


Wow, muchas respuestas, pero recibí este error cuando hice algo ligeramente diferente que ninguna otra cosa ha mencionado.

En pocas palabras, si crea un nuevo objeto y le dice a EF que se modificó con el EntityState.Modified , se generará este error ya que aún no existe en la base de datos. Aquí está mi código:

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

Sí, esto parece una tontería, pero surgió porque el método en cuestión solía haberle pasado foo , ya que ahora solo se le ha pasado algo de someValue y se crea foo .

EntityState.Modified fácil, simplemente cambie EntityState.Modified a EntityState.Added o cambie toda la línea a:

context.MyObject.Add(foo);


Yo tuve el mismo problema. En mi caso, estaba intentando actualizar la clave principal, lo cual no está permitido.


Solo asegúrese de que tanto la tabla como el formulario tengan la clave principal y edmx actualizados.

Descubrí que los errores durante la actualización generalmente se debían a: - Sin clave principal en la tabla - Sin clave principal en la vista / forma de edición (por ejemplo, @Html.HiddenFor(m=>m.Id )


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


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

Mi versión de la fila era nula, así que tuve que agregar esto a la vista que resolvió mi problema