visual ventajas tools studio para net instalar framework for espaƱol desventajas descargar data entity-framework-4.1

entity-framework-4.1 - ventajas - instalar entity framework visual studio 2017



Entidad 4.1 ActualizaciĆ³n de una entidad principal existente con nuevas entidades secundarias (4)

Primero borro la colección de ingredientes existente en la entidad del producto y luego agrego la lista actualizada de ingredientes nuevamente.

Bueno, este es un tipo de ataque de fuerza bruta para actualizar la colección secundaria. EF no tiene ninguna magia para actualizar a los niños, lo que significa: agregar nuevos hijos, eliminar los niños eliminados, actualizar los niños existentes, solo configurando el estado del padre como Modified . Básicamente, este procedimiento lo obliga a eliminar también los hijos anteriores de la base de datos e insertar el nuevo, así:

// product is the detached product with the detached new children collection using (var context = new MyContext()) { var productInDb = context.Products.Include(p => p.Ingredients) .Single(p => p.Id == product.Id); // Update scalar/complex properties of parent context.Entry(productInDb).CurrentValues.SetValues(product); foreach (var ingredient in productInDb.Ingredients.ToList()) context.Ingredients.Remove(ingredient); productInDb.Ingredients.Clear(); // not necessary probably foreach (var ingredient in product.Ingredients) productInDb.Ingredients.Add(ingredient); context.SaveChanges(); }

El mejor procedimiento es actualizar la colección de hijos en la memoria sin eliminar todos los hijos de la base de datos:

// product is the detached product with the detached new children collection using (var context = new MyContext()) { var productInDb = context.Products.Include(p => p.Ingredients) .Single(p => p.Id == product.Id); // Update scalar/complex properties of parent context.Entry(productInDb).CurrentValues.SetValues(product); var ingredientsInDb = productInDb.Ingredients.ToList(); foreach (var ingredientInDb in ingredientsInDb) { // Is the ingredient still there? var ingredient = product.Ingredients .SingleOrDefault(i => i.Id == ingredientInDb.Id); if (ingredient != null) // Yes: Update scalar/complex properties of child context.Entry(ingredientInDb).CurrentValues.SetValues(ingredient); else // No: Delete it context.Ingredients.Remove(ingredientInDb); } foreach (var ingredient in product.Ingredients) { // Is the child NOT in DB? if (!ingredientsInDb.Any(i => i.Id == ingredient.Id)) // Yes: Add it as a new child productInDb.Ingredients.Add(ingredient); } context.SaveChanges(); }

Tengo una aplicación donde puedes crear un nuevo tipo de producto y agregarle a ese producto algunos ingredientes. El producto y los ingredientes son ambas entidades guardadas en una base de datos. La entidad del producto tiene una colección de entidades de ingredientes.

(versión simplificada)

public class Product Public Sub New() Me.Ingredients = New List(Of Ingredient)() End Sub Property Ingredients as ICollection(Of Ingredient) end class

Cuando guardo el producto por primera vez, todo va bien: simplemente lo agrego al contexto y llamo a SaveChanges.

myDataContext.Products.Add(product) myDataContext.SaveChanges()

Tanto el producto (padre) como los ingredientes (niños) se guardan y se vinculan entre sí. Todo está bien.

Sin embargo, cuando agrego / elimino un ingrediente a un producto existente, empiezo a tener problemas. Primero borro la colección de ingredientes existente en la entidad del producto y luego agrego la lista actualizada de ingredientes nuevamente (no reutilizo los ingredientes, agregue el momento). Luego cambio el estado de la entidad del producto a modificado y llamo a savechanges. Sin embargo, al cambiar de estado, obtengo la excepción " Ya existe un objeto con la misma clave en el ObjectStateManager ".

myDataContext.Entry(product).State = EntityState.Modified

Después de la búsqueda "un poco", descubrí que el problema es que todos los ingredientes tienen una clave principal de 0 (ya que aún no se han agregado) y cuando se cambia el estado de la entidad principal (producto), todas las entidades secundarias (ingredientes) ) se adjuntan al contexto con la clave de 0, lo que causa el problema ya que las claves ya no son únicas.

He estado buscando una solución pero no sé cómo resolver este problema. Intenté agregar los ingredientes al contexto antes de cambiar el estado, pero luego falta el vínculo entre el producto y los ingredientes ... ¿Cómo actualizo una entidad principal existente con nuevas entidades secundarias aún no agregadas?

Yo uso Entity Framework 4.1 y Code First.

¡Espero que puedas ayudarme!


Después de muchos meses luchando por entender todo este Entity Framework horrible, espero que esto pueda ayudar a alguien y no pasar por la frustración que he sufrido.

public void SaveOrder(SaleOrder order) { using (var ctx = new CompanyContext()) { foreach (var orderDetail in order.SaleOrderDetails) { if(orderDetail.SaleOrderDetailId == default(int)) { orderDetail.SaleOrderId = order.SaleOrderId; ctx.SaleOrderDetails.Add(orderDetail); }else { ctx.Entry(orderDetail).State = EntityState.Modified; } } ctx.Entry(order).State = order.SaleOrderId == default(int) ? EntityState.Added : EntityState.Modified; ctx.SaveChanges(); } }


Encontré este article reciente en la extensión GraphDiff para DbContext.

Aparentemente es una variante genérica y reutilizable de la de .

Código de ejemplo:

using (var context = new TestDbContext()) { // Update DBcompany and the collection the company and state that the company ''owns'' the collection Contacts. context.UpdateGraph(company, map => map.OwnedCollection(p => p.Contacts)); context.SaveChanges(); }

En otros comentarios; Veo que el autor ha propuesto al equipo de EF usar su código en el número 864 Brindar un mejor soporte para trabajar con entidades desconectadas .


Supongo que esta es una solución más simple.

public Individual { ..... public List<Address> Addresses{get;set;} } //where base.Update from Generic Repository public virtual void Update(T entity) { _dbset.Attach(entity); _dataContext.Entry(entity).State = EntityState.Modified; } //overridden update public override void Update(Individual entity) { var entry = this.DataContext.Entry(entity); var key = Helper.GetPrimaryKey(entry); var dbEntry = this.DataContext.Set<Individual>().Find(key); if (entry.State == EntityState.Detached) { if (dbEntry != null) { var attachedEntry = this.DataContext.Entry(dbEntry); attachedEntry.CurrentValues.SetValues(entity); } else { base.Update(entity); } } else { base.Update(entity); } if (entity.Addresses.Count > 0) { foreach (var address in entity.Addresses) { if (address != null) { this.DataContext.Set<Address>().Attach(address); DataContext.Entry(address).State = EntityState.Modified; } } } }