web-dev-qa-db-fra.com

L'objet ne peut pas être supprimé car il n'a pas été trouvé dans ObjectStateManager dans le framework d'entité 5

J'essaie de supprimer un objet à l'aide d'EntityFramework 5 mais j'obtiens cette erreur . L'objet ne peut pas être supprimé car il n'a pas été trouvé dans ObjectStateManager  
J'utilise la méthode Remove(), car DeleteObject() n'est pas présent dans EF5 . Quelqu'un peut-il m'aider à résoudre ce qui me manque?

Cela ne fonctionne pas pour Remove

localDb.Customers.Remove(new Customer() { CustomerId = id });
                localDb.SaveChanges();

Une autre chose que j'ai essayé de msdn pour changer l'état en Supprimé. Mais ici, il y a une erreur qui dit que tous les champs doivent être présents. Est-il nécessaire d'obtenir le dossier complet puis de le supprimer?

var customer = new Customer(){ CustomerId = id };
                localDb.Customers.Attach(customer);

                localDb.Entry(customer).State = EntityState.Deleted;
                localDb.SaveChanges();

Des entrées?

13
Rameez Ahmed Sayad

Vous pouvez extraire la ligne de la base de données, puis la supprimer, mais cela entraîne 2 allers-retours vers la base de données.

Si vous voulez le faire en un seul coup, votre deuxième version avec Attach fonctionnera - tant que l'entité n'est pas déjà chargée dans le contexte.

L'erreur que vous obtenez est provoquée par la validation EF qui s'exécute avant toute écriture de base de données.

Vous pouvez le désactiver temporairement comme ceci:

bool oldValidateOnSaveEnabled = localDb.Configuration.ValidateOnSaveEnabled;

try
{
  localDb.Configuration.ValidateOnSaveEnabled = false;

  var customer = new Customer { CustomerId = id };

  localDb.Customers.Attach(customer);
  localDb.Entry(customer).State = EntityState.Deleted;
  localDb.SaveChanges();
}
finally
{
  localDb.Configuration.ValidateOnSaveEnabled = oldValidateOnSaveEnabled;
}
25
Nicholas Butler

si vous avez récupéré un objet de la base de données, il est déjà attaché au contexte afin que vous puissiez le supprimer en:

db.myTable.Remove(model);

mais
si vous venez de recevoir un modèle de la vue modifier ou supprimer vue par courrier ou si vous l'avez généré vous-même pour éviter 2 voyages dans la base de données, EF ne le sait pas et vous obtenez une erreur avec la ligne ci-dessus (..n'est pas trouvé dans ObjectStateManager .. ) afin que vous définissiez son état sur "Supprimé" pour informer EF par:

//generate it yourself if not posted from edit/delete view
//var model = new Model { Id = 123 };

//set to delete
db.Entry(model).State = EntityState.Deleted;
db.SaveChanges();
6
Moji

Pouvez-vous simplement faire ça?

var customer = localDb.Customers.Single(o => o.CustomerId == id);
localDb.Customers.Remove(customer);
localDb.SaveChanges();
2
Mike C.

Je sais que cette question est assez ancienne, mais aucune des solutions ci-dessus n'a fonctionné pour moi puisque je supprimais des registres de plusieurs classes/services à la fois et que chacun d'entre eux instanciait son propre contexte de connexion à une base de données.

Ce que j'ai fait pour le résoudre a été d'envoyer le premier contexte créé au reste des classes/services qui allaient accéder à la base de données.

Par exemple, ma serviceA allait supprimer certains de ses registres et appeler serviceB et serviceC pour faire de même avec leurs registres.

Je supprimerais ensuite mes registres sur serviceA et transmettrais en paramètre le contexte créé sur serviceA à serviceB et serviceC.

0
Terkhos
public T Delete<T>(T obj) where T : class
        {
            T existing = context.Set<T>().Find(GetKeys(obj, context));

            if (existing != null)
            {
                context.Set<T>().Remove(existing);
                context.SaveChanges();
                return existing;
            }
            return null;
        }

private object[] GetKeys<T>(T entity, DbContext context) where T : class
        {
            ObjectContext objectContext = ((IObjectContextAdapter)context).ObjectContext;
            ObjectSet<T> set = objectContext.CreateObjectSet<T>();
            var keyNames = set.EntitySet.ElementType
                                                        .KeyMembers
                                                        .Select(k => k.Name).ToArray();
            Type type = typeof(T);

            object[] keys = new object[keyNames.Length];
            for (int i = 0; i < keyNames.Length; i++)
            {
                keys[i] = type.GetProperty(keyNames[i]).GetValue(entity, null);
            }
            return keys;
        }
0
GLeBaTi