Novo subentity não vai salvar quando o pai entidade é salvo
-
02-01-2020 - |
Pergunta
Eu tenho um pai entidade
foo
o que existe no banco de dados, eu tenho uma propriedade de bar
nesta entidade (relação Um-para-muitos).
Foo
é destacado, porque a sua desserializado usando WebApi, então eu faço isso para foo
context.Foos.AddOrUpdate(foo);
Mesmo Se houver uma nova bar
referência anexado a ele, ele não vai ficar guardado, no entanto, ele faz um trabalho como este para uma outra relação que nós temos é uma relação muitos-para-Muitos.Se eu adicionar uma nova entidade para que a coleta será salvo para a sua mesa e também uma linha é adicionada à tabela de relação.
Se eu fizer context.Bars.AddOrUpdate(foo.Bar);
antes de chamar context.Foos.AddOrUpdate(foo);
ele vai salvar o novo bar corretamente para a mesa de bar, mas ele não vai adicionar o correto barId para o foo tabela
@Yuliam Chandra
Se eu entendi sua resposta corretamente (eu acho que você está misturando até bares e foos na sua resposta) isso deve funcionar?
var foo = new Foo();
foo.FooId = 524 //Existing foo;
foo.Bar = new Bar(); //Completely new bar
db.Foos.AddOrUpdate(foo);
db.SaveChanges();
Mas ele não
Solução
Trabalhar com objectos desligados necessidades de código extra.
Se você estiver trabalhando com desconectado objetos, você deve gerenciar manualmente a sincronização.
Se Bar
é uma entidade existente que você precisa para anexá-lo primeiro, para que o Foo
vai ser adicionado como Bar's
crianças.
if (foo.Bar.Id != 0)
{
context.Bars.Attach(foo.Bar);
context.Foos.AddOrUpdate(foo);
}
O exemplo de código acima é semelhante com Course
(Foo
) e Department
(Bar
) exemplo este artigo.
Mas se Bar
é uma nova entidade, você só precisa adicionar Foo
, e , em seguida, Bar
também será adicionado.
else
{
context.Foos.Add(foo);
}
Alguma outra variedade pode ser verificado no minha resposta.
atualização
Antes de explicar melhor, eu gostaria de mostrar o código idêntico.
db.Set<T>().Add(instance)
é igual adb.Entry(instance).State = EntityState.Added;
db.Set<T>().Attach(instance)
é igual adb.Entry(instance).State = EntityState.Unchanged;
A resposta anterior explicou sobre duas condições.
Novo Foo e Bar existente
context.Bars.Attach(foo.Bar);
context.Foos.AddOrUpdate(foo);
Novo Foo e Bar novo
context.Foos.Add(foo);
Especial Adicionados
Added
tem condição especial, uma vez que uma entidade está marcada como Added
.todas as entidades do gráfico será marcado como Added
também, mesmo se qualquer entidade de referência é um objeto existente no banco de dados.Se temos este código, Foo e Bar será adicionado.
var foo = new Foo (); // new foo
foo.Bar = new Bar { BarId = 123 }; // existing bar
db.Set<Foo>().Add(foo);
db.SaveChanges();
Para evitar que isso aconteça, Bar precisa ser ligado primeiro.
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();
Seleção Julie Lerman artigo para mais explicação completa.
A razão pela qual isto acontece é que quando você usa o DbSet.O método Add (que é, Screencasts.Adicionar), não é apenas o estado de raiz entidade marcada "Acrescentou," mas tudo no gráfico que o contexto não era anteriormente ciente de que é marcado também Adicionados.Mesmo que o desenvolvedor pode estar ciente de que o Tópico possui um valor de Id, Entity Framework honre suas EntityState (Adicionado) e cria um comando Inserir banco de dados para o Tópico, independentemente da Identificação existente.
Ajustar A Explicação Com Base Na Sua Atualização
E a sua atualizado questão é sobre a atual Foo e Bar novo.Utilizar o seu código, o resultado não irá adicionar novos Bar e Foo existente não fazer uma relação com as novas Bar.
var foo = new Foo();
foo.FooId = 524 //Existing foo;
foo.Bar = new Bar(); //Completely new bar
db.Foos.AddOrUpdate(foo);
db.SaveChanges();
Se nós adicionar manualmente a Barra junto com AddOrUpdate(foo)
, o resultado ainda não é como o esperado.O novo Bar será adicionado, mas o Foo não tem relação com a nova Barra.
db.Bars.Add(foo.Bar);
db.Foos.AddOrUpdate(foo);
O comportamento de AddOrUpdate
é inconsistente.
Solução
Se você estiver trabalhando com desconectado objetos, você deve gerenciar manualmente a sincronização.
Este código deve funcionar em todas as condições.
- Novo Foo e Bar Novo
- Novo Foo e Bar Existente
- Existente Foo e Bar Novo
- Existente Foo e Bar Existente
Este código depende da identificação (id = 0 é uma nova entidade).
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();
Relacionados AddOrUpdate
, Eu acho que há uma questão aberta que pode ser encontrado aqui.