work unit pattern patron mvc framework entity-framework entity-framework-4 persistence repository-pattern

entity-framework - unit - repository pattern obsolete



¿Es posible eliminar un elemento secundario de la colección y resolver problemas en SaveChanges? (2)

Estamos utilizando Entity Framework Code First con relaciones Foreign Key. Investigamos formas de manejar la eliminación de objetos de una ICollection de entidades en nuestra aplicación.

Cuando tenemos una entidad con relaciones secundarias, podemos agregar objetos directamente a su ICollection usando el método Add. Ahora cuando usas remove obtienes el error

Se produjo System.InvalidOperationException Message = Falló la operación: no se pudo cambiar la relación porque una o más de las propiedades de clave foránea no admiten nulos. Cuando se realiza un cambio en una relación, la propiedad de clave foránea relacionada se establece en un valor nulo. Si la clave externa no admite valores nulos, se debe definir una nueva relación, se debe asignar a la propiedad de clave externa otro valor no nulo o se debe eliminar el objeto no relacionado.

Entiendo que esto se debe a que Eliminar en la colección solo elimina la relación anulando la clave externa. Queríamos escribir nuestra lógica comercial en nuestra entidad y permitir su eliminación.

Así que saque la entidad raíz de su Repositorio por ejemplo Order from OrderRepository y luego llame a algún método específico de la entidad, por ejemplo Order.AddOrderline(Orderline orderline) Esto agrega una OrderLine a las Orders virtual ICollection<OrderLine> OrderLines

Sin embargo, no podemos escribir código como Order.CancelOrderline(int orderLineId) porque simplemente eliminar de ICollection causa un error en los cambios de ahorro.

No parece ser de todos modos para lograr esto simplemente manipulando las colecciones de objetos. Obviamente, podemos eliminar directamente del contexto. Sin embargo, me gustaría hacer que forme parte de la entidad. ¿Podemos limpiar ciertas entidades sin clave externa en el evento SaveChanges de Entity Framework? Obviamente, es necesario decirle a EF qué entidades se pueden eliminar si tienen una clave externa nula.

Actualmente estamos usando un patrón de repositorio para que el controlador no tenga acceso al contexto. Obviamente, podría utilizar un repositorio OrderLine o un método Remove OrderLine en el repositorio de pedidos. Sin embargo, me preguntaba si era posible escribir el código en la entidad sin referencias al mecanismo de persistencia.

¿Pensamientos? ¿Nos estamos equivocando? ¿Otros ORM le permiten eliminar de Colecciones para niños?


Como está descubriendo, si elimina una Entidad de una colección, la Entidad cuelga unida al contexto del objeto y le da un error cuando llama a SaveChanges() ; He utilizado eventos de dominio para habilitar una forma ordenada de eliminar la entidad del contexto del objeto a través de un repositorio.

He detallado este enfoque en mi respuesta a esta pregunta .


No sé si la siguiente es una solución para usted, pero Entity Framework admite la identificación de relaciones . En dicha relación, la clave externa de la entidad hijo (dependiente) del padre (principal) debe ser parte de la clave primaria (compuesta) de la entidad hijo. Por ejemplo, con anotaciones de datos DbContext las clases de modelo deben tener este aspecto:

public class Order { [Key] public int OrderId { get; set; } public ICollection<OrderLine> OrderLines { get; set; } } public class OrderLine { [Key, ForeignKey("Order"), Column(Order = 1)] public int OrderId { get; set; } [Key, Column(Order = 2)] public int OrderLineId { get; set; } public Order Order { get; set; } }

Puede hacer que OrderLineId una identidad autogenerada si lo desea. Lo importante es solo que el FK a la Order es parte del PK.

Un código como este por ejemplo ...

using (var ctx = new MyContext()) { var order = ctx.Orders.Include("OrderLines").Single(o => o.OrderId == 1); var orderLineToDelete = order.OrderLines .FirstOrDefault(ol => ol.OrderLineId == 5); if (orderLineToDelete != null) order.OrderLines.Remove(orderLineToDelete); ctx.SaveChanges(); }

... eliminaría de hecho el orderLineToDelete de la base de datos.

Más detalles están here en la sección " Consideraciones para identificar y relaciones no identificables ".