Question

Je rencontre un problème avec l'entité framework code - d'abord dans MVC3. Je frappe cette exception:

Un objet avec la même clé existe déjà dans l'objetStatanager. L'objetStateManager ne peut pas suivre plusieurs objets avec le même clé.

Ceci est abordé à plusieurs reprises, mais j'ai du mal à utiliser l'une des solutions suggérées dans ma situation.

Voici un échantillon de code:

FestORM.SaleMethod method = new FestORM.SaleMethod
{
    Id = 2,
    Name = "Test Sale Method"
};
FestContext context = new FestContext();

//everything works without this line:
string thisQueryWillMessThingsUp = 
    context.SaleMethods.Where(m => m.Id == 2).Single().Name;

context.Entry(method).State = System.Data.EntityState.Modified;
 context.SaveChanges();

édité pour clarifier: Je tente de mettre à jour un objet existant déjà dans la base de données.

tout fonctionne bien sans la requête notée dans le code. Dans ma demande, mon contrôleur instanticule le contexte et que le même contexte est transmis à plusieurs référentiels utilisés par le contrôleur - donc Je ne suis pas capable de simplement utiliser un contexte différent pour l'opération de requête initiale. J'ai essayé de supprimer l'entité d'être suivie dans l'objetStapeanager, mais je ne peux pas sembler devenir quelque part non plus. J'essaie de trouver une solution qui fonctionnera pour les deux conditions: parfois, je mettrai une mise à jour d'un objet qui est suivi par ObjectStaMeanager et, parfois, cela n'aura pas encore été suivi.

FWIW, mes fonctions de référentiel réel ressemblent à cela, comme le code ci-dessus:

public void Update(T entity)
{
    //works ONLY when entity is not tracked by ObjectStateManager
    _context.Entry(entity).State = System.Data.EntityState.Modified; 
}

public void SaveChanges()
{
    _context.SaveChanges();
}

Des idées? Je me suis battu cela depuis trop longtemps ...

Était-ce utile?

La solution

Le problème est que cette requête

string thisQueryWillMessThingsUp =  
    context.SaleMethods.Where(m => m.Id == 2).Single().Name; 

apporte une instance de l'entité salemethod dans le contexte, puis ce code

context.Entry(method).State = System.Data.EntityState.Modified;

attache une instance différente dans le contexte. Les deux cas ont la même clé primaire. EF pense donc que vous essayez d'attacher deux entités différentes avec la même clé du contexte. Il ne sait pas qu'ils sont censés être la même entité.

Si pour une raison quelconque, vous devez simplement interroger pour le nom, mais je ne veux pas apporter en réalité l'entité complète dans le contexte, vous pouvez le faire:

string thisQueryWillMessThingsUp =           
    context.SaleMethods.Where(m => m.Id == 2).AsNoTracking().Single().Name; 

Si ce que vous attachez à faire est de mettre à jour une entité existante et que vous avez des valeurs pour toutes les propriétés mappées de cette entité, la chose la plus simple à faire est de ne pas exécuter la requête et d'utiliser simplement:

context.Entry(method).State = System.Data.EntityState.Modified;

Si vous ne souhaitez pas mettre à jour toutes les propriétés, éventuellement parce que vous n'avez pas de valeurs pour toutes les propriétés, puis interrogez pour l'entité et la définition des propriétés avant d'appeler SAVECHANGES est une approche acceptable. Il existe plusieurs façons de le faire en fonction de vos besoins exacts. Une façon est d'utiliser la méthode de la propriété, quelque chose comme si:

var salesMethod = context.SaleMethods.Find(2); // Basically equivalent to your query
context.Entry(salesMethod).Property(e => e.Name).CurrentValue = newName;
context.Entry(salesMethod).Property(e => e.SomeOtherProp).CurrentValue = newOtherValue;
context.SaveChanges();

Ces postes de blog contiennent des informations supplémentaires pouvant être utiles:

http://blogs.msdn.com/b/adonet/archive/2011/01/29/USTION-DBContext-in-ef-feature-CTP5-Part-4-add-attach -et-entité-entité-états.aspx

http://blogs.msdn.com/b/adonet/archive/2011/01/30/USTION-DBContext-in-ef-Feature-CTP5-Part-5-working-with-Property -values.aspx

Autres conseils

La réponse évidente serait que vous ne sauverriez pas réellement l'objet de la méthode dans la base de données avant d'appeler:

//everything works without this line:
string thisQueryWillMessThingsUp = context.SaleMethods.Where(m => m.Id == 2).Single().Name;

Cependant, je pense que c'est peut-être un peu un code que vous avez laissé de côté. Et si vous faites hériter de vos entités d'une classe abstraite, c'est-à-dire.

public abstract class BaseClass
{
     public int Id { get; set; }
}

Puis mettez à jour votre référentiel sur

public class Repository<T> where T : BaseClass
{
 .....
    public void Update(T entity)
    {        
        _context.Entry(entity).State = entity.Id == 0 ? System.Data.EntityState.Added : System.Data.EntityState.Modified; 
    }
}

Vous pouvez également ne pas définir l'identifiant de votre salemethod et la laisser générer par la base de données.Le problème pourrait également être parce que l'objet SaleThod dans la base de données a un ID de 2, puis vous essayez d'ajouter un autre objet SALMETHOD avec ID 2. L'erreur que vous voyez découle de tenter d'ajouter un autre objet salemethod avec ID de 2 à l'objetStaemanager.

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