2009-05-22 7 views
2

Ce code ne fait enregistrer les modifications:fortement typées ASP.NET MVC avec Entity Framework

// 
// POST: /SomeType/Edit/5 

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Edit(Guid id, SomeType Model) 
{ 
    db.AttachTo(Model.GetType().Name, Model); 
    db.ApplyPropertyChanges(Model.EntityKey.EntitySetName, Model); 
    db.SaveChanges(); 
    return RedirectToAction("Index"); 
} 

ASP.NET MVC crée le modèle d'objet en tant que type Département EntityObject avec une valeur de EntityState individuelle .

Après avoir utilisé la méthode AttachTo, son EntityState devient Inchangé.

MSDN on Attaching Objects (Entity Framework)

objets sont fixés à l'objet dans un contexte Inchangé état.

En raison de son état Inchangé, la méthode ApplyPropertyChanges ne fait rien.

Je souhaite que l'état à la place soit Modifié.

MSDN on EntityState Enumeration

individuelle
L'objet existe, mais il n'est pas suivi par l'objet Services. Une entité est dans cet état immédiatement après avoir été créée et avant d'être ajoutée à l'objet . Une entité est également dans cet état après avoir été supprimée du contexte en appelant la méthode Detach ou si elle est chargée à l'aide d'un NoTrackingMergeOption.

Inchangé
L'objet n'a pas été modifié depuis qu'il a été chargé dans le contexte ou depuis la dernière fois que la méthode SaveChanges a été appelé.

modifié
L'objet est changé, mais la méthode SaveChanges n'a pas été appelé.

Je ne peux pas définir explicitement une propriété de EntityState EntityObject à modifié. C'est en lecture seule.

Est-il simplement impossible d'avoir des contrôleurs MVC fortement typés avec EntityObjects?

+0

http://stackoverflow.com/questions/922402/strongly-typed-asp-net-mvc-with-ado-net-entity-framework –

Répondre

8

Vous devez obtenir ObjectStateManager à partir de votre ObjectContext. Avec le ObjectStateManager, vous pouvez explicitement définir l'état de votre objet sans avoir besoin de faire un appel à la base de données:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Edit(Guid id, SomeType Model) 
{ 
    db.AttachTo(Model.GetType().Name, Model); 

    ObjectStateManager stateMgr = db.ObjectStateManager; 
    ObjectStateEntry stateEntry = stateMgr.GetObjectStateEntry(model); 
    stateEntry.SetModified(); // Make sure the entity is marked as modified 
    //db.ApplyPropertyChanges(Model.EntityKey.EntitySetName, Model); 

    db.SaveChanges(); 
    return RedirectToAction("Index"); 
} 

Le ObjectStateEntry vous permet également d'appliquer des données plus fines état via le changement SetModifiedProperty. Si vous appelez SetModified, EF traitera l'entité entière comme modifiée et conservera toutes les propriétés dans le magasin de données. Avec SetModifiedProperty, EF peut optimiser les requêtes et impliquer uniquement les propriétés qui ont réellement changé. L'utilisation de SetModifiedProperty est évidemment plus complexe, car vous devez généralement connaître la valeur d'origine de chaque propriété.

J'espère que cette aide. ObjectStateManager est un petit outil puissant dans la boîte à outils EF, et peut aider à améliorer les performances morbides et l'efficacité d'EF v1.0.

+0

SetModifiedProperty fonctionne comme prévu. Mais, SetModified ne semble pas traiter l'entité entière comme modifiée. Plutôt que de "conserver toutes les propriétés dans le magasin de données", il n'en persiste aucune. –

+0

C'est un peu bizarre ... il peut y avoir quelque chose d'autre qui doit être fait ... mais cela ressemble à un bug quelque part. – jrista

+1

Grande réponse et nouveau terrain pour moi en ce qui concerne ObjectContext, alors merci pour la connaissance. J'ai récemment eu un problème similaire que j'ai résolu en transformant temporairement le CO en un DbContext: http://stackoverflow.com/questions/33714849/objectcontext-with-entity-framework-6-inserting-duplicates-on-existing-related- e –

1

Cela fonctionne:

// 
// POST: /SomeType/Edit/5 

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Edit(Guid id, SomeType Model) 
{ 
    Model.EntityKey = (from SomeType s in db.SomeType 
         where s.Id == id 
         select s).FirstOrDefault().EntityKey; 
    db.ApplyPropertyChanges(Model.EntityKey.EntitySetName, Model); 
    db.SaveChanges(); 
    return RedirectToAction("Index"); 
} 

Mais est-il un moyen sans interroger la base de données?

1

Qu'advient-il si vous ajoutez une ligne:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Edit(Guid id, SomeType Model) 
{ 
    db.AttachTo(Model.GetType().Name, Model); 
    Model.SomeProperty = Model.SomeProperty; // This looks hacky... =(
    db.ApplyPropertyChanges(Model.EntityKey.EntitySetName, Model); 
    db.SaveChanges(); 
    return RedirectToAction("Index"); 
} 

Est-ce que le changement d'état?

+0

j'ai essayé Model.Id = Modèle. Id mais cela a provoqué une exception car ce champ particulier est protégé par Entity Framework. Je n'ai pas essayé d'autres. –

+0

Oui, l'ID est en lecture seule. Essayez un autre ... =) –

3

J'ai trouvé aucun de ce qui précède ne semblait fonctionner pour moi, mais l'exemple de guide MSDN a fait ce qui est où vous obtenez l'élément d'origine du contexte, puis attachez l'élément mis à jour.

Deuxième exemple:

http://msdn.microsoft.com/en-us/library/bb896248.aspx#Mtps_DropDownFilterText

private static void ApplyItemUpdates(SalesOrderDetail updatedItem){ 
// Define an ObjectStateEntry and EntityKey for the current object. 
EntityKey key; 
object originalItem; 

using (AdventureWorksEntities advWorksContext = 
    new AdventureWorksEntities()) 
{ 
    try 
    { 
     // Create the detached object's entity key. 
     key = advWorksContext.CreateEntityKey("SalesOrderDetail", updatedItem); 

     // Get the original item based on the entity key from the context 
     // or from the database. 
     if (advWorksContext.TryGetObjectByKey(key, out originalItem)) 
     { 
      // Call the ApplyPropertyChanges method to apply changes 
      // from the updated item to the original version. 
      advWorksContext.ApplyPropertyChanges(
       key.EntitySetName, updatedItem); 
     } 

     advWorksContext.SaveChanges(); 
    } 
    catch (InvalidOperationException ex) 
    { 
     Console.WriteLine(ex.ToString()); 
    } 
} 

}

1

J'ai ce travail, mais ce iam pas en mesure d'obtenir à est l'entité mère de SalesOrderDetail Comment puis-je obtenir à elle ? SalesOrderDetail.SalesOrderHead est null et entityreference est null.

Ma routine d'édition a uniquement accès à l'ID de SalesOrderDetail.

Merci Sri

+0

Essayez le lien «Poser une question» pour lancer une nouvelle question. Votre problème recevra plus d'attention. –

Questions connexes