J'essaye de supprimer une ligne de la base de données en utilisant ce code

public ListPicture GetPicture(string Id)
{
  ListPicture pic = Pictures.AsNoTracking().FirstOrDefault(x => x.pId == Id);
  return pic;
}

public void DeletePicture(string Id)
{
  ListPicture pic = GetPicture(Id);
  if( pic != null)
  {
     Pictures.Remove(pic);
  }
  SaveChanges();
}

Lors de la suppression, j'ai cette erreur

System.InvalidOperationException: l'objet ne peut pas être supprimé car il n'a pas été trouvé dans ObjectStateManager.

J'ai essayé de joindre la photo de l'entité à Pictures

public void DeletePicture(string Id)
{
  ListPicture pic = GetPicture(Id);
  if( pic != null)
  {
      Pictures.Attach(pic);
      Pictures.Remove(pic);
   }
   SaveChanges();
 }

C'est l'erreur est:

System.InvalidOperationException: l'attachement d'une entité de type «Album.DatabaseContext.ListPicture» a échoué car une autre entité du même type a déjà la même valeur de clé primaire.

La fonction GetPicture est utilisée plusieurs fois dans mon application, comment puis-je résoudre ce problème

2
melom 20 avril 2017 à 21:22

3 réponses

Meilleure réponse

Eh bien, apparemment, l'entité doit être suivie (chargée) dans le contexte.

Alors n'utilisez pas non plus la méthode GetPicture (je sais, duplication de code mais ...):

ListPicture pic = Pictures.FirstOrDefault(x => x.pId == Id);
if (pic != null)
{
    Pictures.Remove(pic);
}
SaveChanges();

Ou si le Pictures est DbSet<T> (comme il semble d'après le code publié), vous pouvez utiliser le Find à la place:

ListPicture pic = Pictures.Find(Id);
if (pic != null)
{
    Pictures.Remove(pic);
}
SaveChanges();

Les deux approches garantiront que l'instance retournée est attachée au contexte.

1
Ivan Stoev 20 avril 2017 à 18:33

Si vous n'êtes pas sûr qu'il sera joint ou non ( et en fonction des exceptions que vous obtenez, il peut s'agir de l'un ou l'autre ou ), vous pouvez ajouter une coche sur l'instance DbContext pour voir s'il est attaché et attachez-le si ce n'est pas le cas. Cela nécessite l'accès à l'instance DbContext qui est utilisée.

Assurez-vous également de toujours renvoyer une entité attachée et de ne pas utiliser AsNoTracking().

public void DeletePicture(string Id)
{
  ListPicture pic = GetPicture(Id);
  if( pic != null)
  {
      // add check if instance is attached
      if(contextInstance.Entry(pic).State == System.Data.Entity.EntityState.Detached)
        Pictures.Attach(pic);
      Pictures.Remove(pic);
   }
   SaveChanges(); // this could be moved to inside the if block
}
1
Igor 20 avril 2017 à 18:41

Lorsque vous utilisez AsNoTracking, EF ne gère pas les données des entités qui ont été chargées dans le proxy. Autrement dit, c'est une entité qui ne dépend plus d'EF pour rien.

Cependant, cette entité existe dans la base de données. Lors de la tentative d'exécution d'un Attach, l'EF vérifie qu'il existe déjà quelqu'un avec le même Id et lève l'exception.

Ma suggestion est:

1: Supprimez le AsNoTracking de la méthode GetPicture. 2: Si vous ne pouvez pas, effectuez votre méthode de suppression comme ceci:

public ListPicture GetPicture(string Id)
{
    ListPicture pic = Pictures.AsNoTracking().FirstOrDefault(x => x.pId == Id);
    return pic;
}

public void DeletePicture(string Id)
{
    ListPicture pic = Pictures.Find(id);
    if( pic != null)
    {
       Pictures.Remove(pic);
    }
    SaveChanges();
}
2
Jedi31 20 avril 2017 à 18:37