Las dos entidades son una relación de uno a muchos (construido por la primera API fluida del código).
public class Parent
{
public Parent()
{
this.Children = new List<Child>();
}
public int Id { get; set; }
public virtual ICollection<Child> Children { get; set; }
}
public class Child
{
public int Id { get; set; }
public int ParentId { get; set; }
public string Data { get; set; }
}
En mi controlador WebApi, tengo acciones para crear una entidad principal (que funciona bien) y actualizar una entidad principal (que tiene algún problema). La acción de actualización se ve así:
public void Update(UpdateParentModel model)
{
//what should be done here?
}
Actualmente tengo dos ideas:
Obtenga una entidad principal rastreada nombrada
existing
pormodel.Id
y asigne valoresmodel
uno por uno a la entidad. Esto suena estúpido. Y enmodel.Children
No sé qué hijo es nuevo, qué hijo se modifica (o incluso se elimina).Cree una nueva entidad principal a través de
model
, y adjúntela al DbContext y guárdela. Pero, ¿cómo puede saber DbContext el estado de los hijos (nueva adición / eliminación / modificación)?
¿Cuál es la forma correcta de implementar esta función?
fuente
Respuestas:
Debido a que el modelo que se publica en el controlador WebApi se separa de cualquier contexto de entidad-marco (EF), la única opción es cargar el gráfico de objeto (padre, incluidos sus hijos) de la base de datos y comparar qué hijos se han agregado, eliminado o actualizado. (A menos que realice un seguimiento de los cambios con su propio mecanismo de seguimiento durante el estado desconectado (en el navegador o donde sea), que en mi opinión es más complejo que el siguiente). Podría verse así:
...CurrentValues.SetValues
puede tomar cualquier objeto y asignar valores de propiedad a la entidad adjunta en función del nombre de la propiedad. Si los nombres de propiedad en su modelo son diferentes de los nombres en la entidad, no puede usar este método y debe asignar los valores uno por uno.fuente
existingParent.Children.Add(newChild)
secundarios , no se puede hacer porque la búsqueda existente de Linux linq devolverá la entidad recientemente agregada, por lo que esa entidad se actualizará. Solo necesita insertar en una lista temporal y luego agregar.existingChild
consulta LINQ:.Where(c => c.ID == childModel.ID && c.ID != default(int))
He estado jugando con algo como esto ...
que puedes llamar con algo como:
Desafortunadamente, esto se cae si hay propiedades de colección en el tipo secundario que también necesitan actualizarse. Considerar tratar de resolver esto pasando un IRepository (con métodos CRUD básicos) que sería responsable de llamar a UpdateChildCollection por sí solo. Llamaría al repositorio en lugar de llamadas directas a DbContext.Entry.
No tengo idea de cómo funcionará todo a escala, pero no estoy seguro de qué más hacer con este problema.
fuente
toAdd.ForEach(i => (selector(dbItem) as ICollection<Tchild>).Add(i.Value));
debería resolver el problema n -> n.Ok muchachos. Tuve esta respuesta una vez, pero la perdí en el camino. ¡Tortura absoluta cuando sabes que hay una mejor manera, pero no puedo recordarla ni encontrarla! Es muy simple. Acabo de probarlo de varias maneras.
¡Puede reemplazar toda la lista por una nueva! El código SQL eliminará y agregará entidades según sea necesario. No hay necesidad de preocuparse por eso. Asegúrese de incluir la colección infantil o ningún dado. ¡Buena suerte!
fuente
Si está utilizando EntityFrameworkCore, puede hacer lo siguiente en la acción posterior de su controlador (El método Adjuntar adjunta recursivamente propiedades de navegación, incluidas colecciones):
Se supone que cada entidad que se actualizó tiene todas las propiedades establecidas y proporcionadas en los datos de publicación del cliente (por ejemplo, no funcionará para la actualización parcial de una entidad).
También debe asegurarse de estar utilizando un contexto de base de datos de marco de entidad nuevo / dedicado para esta operación.
fuente
Así es como resolví este problema. De esta manera, EF sabe qué agregar y qué actualizar.
fuente
Existen algunos proyectos que facilitan la interacción entre el cliente y el servidor en lo que respecta a guardar un gráfico de objeto completo.
Aquí hay dos que te gustaría ver:
Los dos proyectos anteriores reconocen las entidades desconectadas cuando se devuelve al servidor, detectan y guardan los cambios y devuelven los datos afectados por el cliente.
fuente
La prueba de concepto
Controler.UpdateModel
no funcionará correctamente.Clase completa aquí :
fuente
@Charles McIntosh realmente me dio la respuesta para mi situación en que el modelo aprobado fue separado. Para mí, lo que finalmente funcionó fue guardar primero el modelo aprobado ... luego continuar agregando los niños como ya lo estaba antes:
fuente
Para desarrolladores de VB.NET Use este sub genérico para marcar el estado secundario, fácil de usar
fuente
fuente
fuente
Aquí está mi código que funciona bien.
fuente