Pregunta

Tengo una entidad matriz

foo que existe en la base de datos, tengo una propiedad bar en esta entidad (relación uno a muchos).

Foo está desconectado porque se deserializa usando WebApi, así que hago esto para foo

context.Foos.AddOrUpdate(foo);

Incluso si hay una nueva bar referencia 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 lo hago context.Bars.AddOrUpdate(foo.Bar); antes de llamar context.Foos.AddOrUpdate(foo); guardará la nueva barra correctamente en la tabla de barras, pero no agregará el barId correcto a la tabla foo

@Yuliam Chandra

Si entiendo tu respuesta correctamente (creo que estás mezclando compases y foos en tu respuesta), ¿esto 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

¿Fue útil?

Solución

Trabajar con objetos desconectados necesita código adicional.

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

Fuente

Si Bar es una entidad existente, primero debe adjuntarla, por lo que Foo se agregará como Bar's niños.

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

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

Pero si Bar es una nueva entidad que solo necesitas agregar Foo, entonces Bar También se agregará.

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

Alguna otra variedad se puede consultar mi respuesta.

actualizar

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

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

La respuesta anterior explicaba dos condiciones.

  • Nuevo 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 está marcada 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 esto suceda, primero es necesario conectar Bar.

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();

Controlar Artículo de Julie Lerman para una explicación más completa.

La razón por la que sucede es que cuando usa el método dbset.add (es decir, screepenCasts.add), no solo el estado de la entidad raíz es marcado "agregado", sino todo en el gráfico que el contexto no estaba al tanto de está marcado también agregado.A pesar de que el desarrollador puede ser consciente de que el tema tiene un valor de identificación existente, Entity Framework honra a su EntityState (agregado) y crea un comando Insertar Database para el tema, independientemente de la ID existente.

Ajuste la explicación según su actualización

Y su pregunta actualizada es sobre Foo existente y la nueva Bar.Usando su código, el resultado no agregará una nueva barra y el 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 todavía no es el esperado.Se agregará la nueva Bar, pero Foo no tendrá relación con la nueva Bar.

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 manualmente la sincronización.

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

  • Nuevo Foo y Nuevo Bar
  • Nuevo Foo y barra existente
  • Foo existente y nueva barra
  • Foo existente y barra existente

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

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();

Relacionado con AddOrUpdate, Creo que hay un tema abierto que se puede encontrar. aquí.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top