c# entity-framework entity-framework-6.1

c# - La nueva subentidad no se guardarĂ¡ cuando se guarde la entidad principal



entity-framework entity-framework-6.1 (1)

Trabajar con objetos desconectados necesita código adicional.

Si está trabajando con objetos desconectados, debe administrar la sincronización manualmente.

Fuente

Si Bar es una entidad existente, primero debes adjuntarla, por lo que Foo se agregará como hijos Bar''s .

if (foo.Bar.Id != 0) { context.Bars.Attach(foo.Bar); context.Foos.AddOrUpdate(foo); }

El ejemplo del código anterior es similar con el ejemplo de Course ( Foo ) y Department ( Bar ) en este artículo .

Pero si Bar es una entidad nueva, solo necesita agregar Foo , entonces también se agregará Bar .

else { context.Foos.Add(foo); }

Se puede verificar alguna otra variedad en mi respuesta .

actualizar

Antes de seguir explicando, me gustaría mostrar un código idéntico.

  • db.Set<T>().Add(instance) es igual a db.Entry(instance).State = EntityState.Added;
  • db.Set<T>().Attach(instance) es igual a db.Entry(instance).State = EntityState.Unchanged;

La respuesta anterior explicaba dos condiciones.

  • Nueva Foo y Bar existente

    context.Bars.Attach(foo.Bar);

    context.Foos.AddOrUpdate(foo);

  • Nuevo Foo y nuevo Bar

    context.Foos.Add(foo);

Especial agregado

Added tiene una condición especial, una vez que una entidad se marca como Added . todas las entidades en el gráfico se marcarán como Added también, incluso si cualquier entidad de referencia es un objeto existente en la base de datos. Si tenemos este código, se agregarán Foo y Bar.

var foo = new Foo (); // new foo foo.Bar = new Bar { BarId = 123 }; // existing bar db.Set<Foo>().Add(foo); db.SaveChanges();

Para evitar que eso suceda, Bar debe estar conectado primero.

var foo = new Foo (); // new foo foo.Bar = new Bar { BarId = 123 }; // existing bar db.Set<Bar>().Attach(bar); db.Set<Foo>().Add(foo); db.SaveChanges();

Consulte el artículo de Julie Lerman para una explicación más completa.

La razón por la que sucede es que cuando utiliza el método DbSet.Add (es decir, Screencasts.Add), no solo el estado de la entidad raíz está marcado como "Agregado", sino que todo en el gráfico que el contexto no conocía previamente está marcado como Agregado también. Aunque el desarrollador puede estar al tanto de que el Tema tiene un valor Id existente, Entity Framework respeta su EntityState (Added) y crea un comando Insert database para el Tema, independientemente del Id existente.

Ajuste la explicación en función de su actualización

Y su pregunta actualizada es sobre Foo existente y el nuevo Bar. Usando su código, el resultado no agregará una nueva barra y Foo existente no establecerá una relación con la nueva barra.

var foo = new Foo(); foo.FooId = 524 //Existing foo; foo.Bar = new Bar(); //Completely new bar db.Foos.AddOrUpdate(foo); db.SaveChanges();

Si agregamos manualmente la barra junto con AddOrUpdate(foo) , el resultado sigue sin ser el esperado. Se agregará la nueva barra, pero Foo no tendrá relación con la nueva barra.

db.Bars.Add(foo.Bar); db.Foos.AddOrUpdate(foo);

El comportamiento de AddOrUpdate es inconsistente.

Solución

Si está trabajando con objetos desconectados, debe administrar la sincronización manualmente.

Este código debería funcionar en todas las condiciones.

  • Nueva Foo y New Bar
  • Nueva Foo y Bar existente
  • Existente Foo y New Bar
  • Existente Foo y Existing Bar

Este código depende de la identificación (id = 0 es una nueva entidad).

db.Entry(foo).State = foo.FooId == 0 ? EntityState.Added : EntityState.Modified; if (foo.Bar != null) { db.Entry(foo.Bar).State = foo.Bar.BarId == 0 ? EntityState.Added : EntityState.Modified; ^^^ // If you don''t want to change the Bar while creating a relationship between // Foo and with existing Bar, you can change // `EntityState.Modified` with `EntityState.Unchanged` } db.SaveChanges();

En relación con AddOrUpdate , creo que hay un problema abierto que se puede encontrar aquí .

Tengo una entidad matriz

foo que existe en el DB, tengo una bar propiedades en esta entidad (relación de uno a muchos).

Foo está desapegado porque se deserializó usando WebApi, así que hago esto para foo

context.Foos.AddOrUpdate(foo);

Incluso si hay una nueva referencia de bar adjunta, no se guardará, sin embargo, funciona así para otra relación que tenemos, que es una relación de muchos a muchos. Si agrego una nueva entidad a esa colección, se guardará en su tabla y también se agregará una fila a la tabla de relaciones.

Si hago context.Bars.AddOrUpdate(foo.Bar); antes de llamar a context.Foos.AddOrUpdate(foo); guardará la nueva barra correctamente en la barra, pero no agregará la barra correcta a la tabla foo

@Yuliam Chandra

Si entiendo tu respuesta correctamente (creo que estás mezclando barras y foos en tu respuesta), ¿debería funcionar?

var foo = new Foo(); foo.FooId = 524 //Existing foo; foo.Bar = new Bar(); //Completely new bar db.Foos.AddOrUpdate(foo); db.SaveChanges();

Pero no lo hace