Question

J'ai une entité mère

foo qui existe dans la base de données, j'ai une propriété bar sur cette entité (Relation un à plusieurs).

Foo est détaché car il est désérialisé à l'aide de WebApi, donc je fais cela pour foo

context.Foos.AddOrUpdate(foo);

Même s'il y a un nouveau bar référence qui lui est attachée, elle ne sera pas enregistrée, mais elle fonctionne comme ceci pour une autre relation que nous avons qui est une relation Plusieurs à plusieurs.Si j'ajoute une nouvelle entité à cette collection, elle sera enregistrée dans sa table et une ligne est également ajoutée à la table des relations.

Si je fais context.Bars.AddOrUpdate(foo.Bar); avant d'appeler context.Foos.AddOrUpdate(foo); il enregistrera correctement la nouvelle barre dans la table bar, mais il n'ajoutera pas le bon barId à la table foo

@Yuliam Chandra

Si je comprends bien votre réponse (je pense que vous mélangez bars et foos dans votre réponse), cela devrait fonctionner ?

var foo = new Foo();
foo.FooId = 524 //Existing foo;

foo.Bar = new Bar(); //Completely new bar    
db.Foos.AddOrUpdate(foo);
db.SaveChanges();

Mais ce n'est pas le cas

Était-ce utile?

La solution

Travailler avec des objets déconnectés nécessite du code supplémentaire.

Si vous travaillez avec des objets déconnectés, vous devez gérer manuellement la synchronisation.

Source

Si Bar est une entité existante, vous devez d'abord l'attacher, donc Foo sera ajouté comme Bar's enfants.

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

L'exemple de code ci-dessus est similaire à Course (Foo) et Department (Bar) exemple dans Cet article.

Mais si Bar est une nouvelle entité qu'il vous suffit d'ajouter Foo, alors Bar seront également ajoutés.

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

Une autre variété peut être vérifiée ma réponse.

mise à jour

Avant d'expliquer davantage, j'aimerais afficher un code identique.

  • db.Set<T>().Add(instance) est égal à db.Entry(instance).State = EntityState.Added;
  • db.Set<T>().Attach(instance) est égal à db.Entry(instance).State = EntityState.Unchanged;

La réponse précédente expliquait deux conditions.

  • Nouveau Foo et Bar existant

    context.Bars.Attach(foo.Bar);

    context.Foos.AddOrUpdate(foo);

  • Nouveau Foo et nouveau Bar

    context.Foos.Add(foo);

Spécial ajouté

Added a une condition spéciale, une fois qu'une entité est marquée comme Added.toutes les entités du graphique seront marquées comme Added également, même si une entité de référence est un objet existant dans la base de données.Si nous avons ce code, Foo et Bar seront ajoutés.

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

Pour éviter que cela ne se produise, Bar doit d’abord être attaché.

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

Vérifier Article de Julie Lerman pour une explication plus complète.

La raison pour laquelle cela se produit est que lorsque vous utilisez la méthode dbset.add (c'est-à-dire ScreencastS.Add), non seulement l'état de l'entité racine est marqué «ajouté», mais tout dans le graphique que le contexte n'était pas auparavant auparavant auparavant. est marqué également ajouté.Même si le développeur peut être conscient que le sujet a une valeur d'identification existante, l'entité Framework honore son entité (ajouté) et crée une commande de base de données d'insertion pour le sujet, quel que soit l'ID existant.

Ajustez l'explication en fonction de votre mise à jour

Et votre question mise à jour concerne les Foo existants et le nouveau Bar.En utilisant votre code, le résultat n'ajoutera pas de nouvelle Bar et les Foo existants n'établiront pas de relation avec la nouvelle Bar.

var foo = new Foo();
foo.FooId = 524 //Existing foo;

foo.Bar = new Bar(); //Completely new bar    
db.Foos.AddOrUpdate(foo);
db.SaveChanges();

Si nous ajoutons manuellement la barre avec AddOrUpdate(foo), le résultat n'est toujours pas celui attendu.Le nouveau Bar sera ajouté, mais Foo n'aura aucune relation avec le nouveau Bar.

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

Le comportement de AddOrUpdate est incohérent.

Solution

Si vous travaillez avec des objets déconnectés, vous devez gérer manuellement la synchronisation.

Ce code devrait fonctionner dans toutes les conditions.

  • Nouveau Foo et Nouveau Bar
  • Nouveau Foo et bar existant
  • Foo existant et nouveau bar
  • Foo existant et barre existante

Ce code dépend de l'identifiant (id = 0 est une nouvelle entité).

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

Relatif à AddOrUpdate, je pense qu'il y a un problème ouvert qui peut être trouvé ici.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top