3 votes

AsNoTracking duplication d'entités

Désolé pour mon mauvais anglais - j'utilise EF 5 (Code First) dans une application WPF (.net 4.5). Chaque fenêtre a son propre contexte.

J'ai un modèle comme celui-ci (code omis pour des raisons de brièveté) :

public class Car
{
  public string Model { get; set; }  
  public int BrandId { get; set; }  
  public virtual Brand Brand { get; set; }
}

J'utilise des comboboxes pour permettre à l'utilisateur d'associer une Brand à un Car . Le problème est qu'à chaque fois que j'enregistre un Car un nouveau, dupliqué Brand sont également sauvegardés. Cela se produit parce que je charge la combobox avec AsNoTracking() .

Maintenant, je charge la combobox avec AsNoTracking() parce que j'avais du mal à charger les changements sur le Brand réalisés dans d'autres instances de DbContext (à l'aide de myContext.Set<Brand>().Load() ).

Ma question est donc la suivante : comment résoudre ce problème ? S'il existe un autre moyen de forcer le rechargement d'une collection (sans utiliser la commande AsNoTracking ), ce serait bien. Il serait encore plus agréable de pouvoir informer EF que l'option AsNoTracking Les entités chargées ne sont pas nouvelles.

EDIT 1 : @Mark : Merci, attacher l'entité au contexte a fait l'affaire. Mais j'utilise une classe de base générique qui fait la validation et enregistre les données pour tous mes formulaires, donc attacher manuellement les entités n'est pas très pratique... sur la base de votre suggestion, j'ai fini par faire ceci, après avoir ajouté l'entité Car et avant de l'enregistrer :

var entities = (((IObjectContextAdapter)ctx).ObjectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added));

foreach (var item in entities)
{
    if ((item.Entity as EntityBase).Id > 0)
    {
        item.ObjectStateManager.ChangeObjectState(item.Entity, EntityState.Unchanged);
    }
}

(toutes mes entités héritent d'EntityBase et toutes mes clés sont générées par la base de données). Cela a bien fonctionné mais j'aimerais avoir un deuxième avis... est-ce que c'est bon ou y a-t-il un moyen plus simple de le faire ?

3voto

Mark Oreta Points 7490

Ce qui se passe, c'est que votre contexte ne connaît pas la marque qui est attachée à la voiture, donc il en crée une nouvelle qui correspond à votre clé étrangère. Vous devriez attacher la marque au contexte avant de sauvegarder :

context.Brands.Attach(brand);

Vous pouvez recharger la marque individuelle avant de l'enregistrer en la rechargeant individuellement :

db.Entry(brand).Reload();

Si vous ne voulez pas vraiment persister cualquier Si vous modifiez la marque lorsque vous enregistrez une voiture, vous pouvez indiquer au contexte que la marque n'a pas été modifiée et empêcher les mises à jour.

context.Entry(brand).State = EntityState.Unchanged;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X