2011-10-18 9 views
5

Estoy usando primero el código de entidad de marco y exponiendo la base de datos de northwind a través de una interfaz HTTP REST de WCF.Vuelva a conectar un gráfico de entidad y detecte los cambios en la colección

No he expuesto la tabla OrderDetails (artículos de pedido) ya que no tiene sentido crear un pedido y luego agregar cada OrderDetail requerido por separado a través de otro servicio. En mi opinión, debe ser una transacción atómica que tenga éxito o fracase como tal. Por lo tanto, incluyo la colección Order.OrderDetails al pasar al cliente y supongo que voy a obtener uno cuando se crea o actualiza un pedido.

El problema, sin embargo, parece ser la detección de cambios en la colección OrderDetails al volver a conectar la entidad Order para una actualización. El orden en sí se puede configurar como modificado para actualizar esas propiedades, pero esto no se aplica en cascada a los artículos OrderDetail. De modo que puedo pasar manualmente y configurar los actualizados para modificarlos, pero el problema radica en averiguar cuáles se actualizan en primer lugar. Configurar un nuevo OrderDetail para modificar causará un error cuando intente guardar.

He leído una recomendación para establecer Id de los nuevos elementos de la colección en 0 y en el servidor usar eso para decidir si es nuevo o existente. Northwind, sin embargo, utiliza una clave compuesta entre OrderID y ProductID para OrderDetails. Ambos tendrán que ser configurados por el cliente, por lo que no puedo encontrar una manera de detectar cuál es nuevo. Además, un OrderDetail eliminado no existirá en el gráfico separado y tendré que averiguar qué se ha eliminado y eliminarlo explícitamente.

Cualquier consejo sería muy apreciado.

public override Order Update(Order entity) 
{ 
    dbset.Attach(entity); 
    DataContext.Entry(entity).State = EntityState.Modified; 

    foreach (var orderDetail in entity.OrderDetails) 
    { 
     DataContext.Entry(orderDetail).State = EntityState.Modified; 
    } 

    return entity; 
} 

Respuesta

4

Esto es common and complex issue y no hay magia que lo haga por usted. Mi solución (y la única que funciona en todos los escenarios) fue para cargar el Order de nuevo en su método de actualización manualmente y combinar los cambios:

public override Order Update(Order entity) 
{ 
    // No attach of entity 

    var attached = DataContext.Orders.Include(o => o.OrderDetails).SingleOrDefault(...); 
    if (attached == null) ... 

    // Merge changes from entity to attached - if you change any property 
    // it will be marked as modified automatically 

    foreach (var detail in attached.OrderDetails.ToList()) 
    { 
     // ToList is necessary because you will remove details from the collection 

     // if detail exists in entity check if it must be updated and set its state 

     // if detail doesn't exists in entity remove if from collection - if it is \ 
     // aggregation (detail cannot exists without Order) you must also delete it 
     // from context to ensure it will be deleted from the database 
    } 

    foreach (var detail in entity.OrderDetails) 
    { 
     // if it doesn't exists in attached create new detail instance, 
     // fill it from detail in entity and add it to attached entity - 
     //you must not use the same instance you got from the entity 
    } 

    DataContext.SaveChanges(); 

    return entity; 
} 

Puede haber también es necesario comprobar manualmente las marcas de tiempo si se utilizan.

Escenario alternativo es lo que ha descrito con 0 utilizado para nuevos detalles e ID negativo para los detalles eliminados, pero esa es la lógica que debe hacerse en el cliente. También funciona solo en algunos casos.

+0

Gran respuesta. ¡Gracias por tomarse el tiempo! –

+0

¿No cree que tiene alguna idea de por qué el equipo de EF decidió no seguir el escenario de adjuntar gráficos de entidad y hacerlo un poco más automático? Estoy pensando que podría deberse a no querer permitir que el cliente actualice, digamos Producto en una orden - Artículo de pedido - Escenario del producto. –

+0

Cuanto más pienso en este tema, más creo que la automatización total no es posible o confiable (la confiabilidad es exactamente lo que usted describe; la actualización automática podría modificar entidades que no desea modificar). –

Cuestiones relacionadas