1

Jedes Mal, wenn ich aktualisiert meine Platte wollen, bin ich die folgende Fehlermeldung erhalten:EntityFramework 7 Fehler bei der Aufzeichnung der Aktualisierung

"The instance of entity type 'User' cannot be tracked because another instance of this type with the same key is already being tracked. When adding new entities, for most key types a unique temporary key value will be created if no key is set (i.e. if the key property is assigned the default value for its type). If you are explicitly setting key values for new entities, ensure they do not collide with existing entities or temporary values generated for other new entities. When attaching existing entities, ensure that only one entity instance with a given key value is attached to the context."

Hier ist mein Code:

public void SaveRecipient(Recipient myRecipient) 
{ 
    if (myRecipient.RecipientGUID == Guid.Empty) 
    { 
     myRecipient.RecipientGUID = Guid.NewGuid(); 

     foreach (ContactMethod tmpCM in myRecipient.ContactMethods) 
     { 
      context.Entry(tmpCM.Type).State = EntityState.Unchanged; 
     } 

     context.Entry(myRecipient.LastModifiedBy).State = EntityState.Unchanged; 
     context.Entry(myRecipient.Owner).State = EntityState.Unchanged; 
     context.Entry(myRecipient.CreatedBy).State = EntityState.Unchanged; 

     context.Recipients.Add(myRecipient); 
    } 
    else 
    { 
     var dbRecipient = context.Recipients 
      .Include(a => a.ContactMethods).ThenInclude(t => t.Type) 
      .Include(b => b.CreatedBy) 
      .Include(c => c.LastModifiedBy) 
      .Include(d => d.Owner).ThenInclude(o => o.Users) 
      .FirstOrDefault(x => x.RecipientGUID == myRecipient.RecipientGUID); 

     if (dbRecipient != null) 
     { 
      dbRecipient.FirstName = myRecipient.FirstName; 
      dbRecipient.LastName = myRecipient.LastName; 
      dbRecipient.Company = myRecipient.Company; 

      foreach (ContactMethod tmpCM in myRecipient.ContactMethods) 
      { 
       var dbCM = dbRecipient.ContactMethods.FirstOrDefault(x => x.ContactMethodGUID == tmpCM.ContactMethodGUID); 

       if (dbCM != null) 
       { 
        dbCM.CountryCode = tmpCM.CountryCode; 
        dbCM.Identifier = tmpCM.Identifier; 
        dbCM.IsPreferred = tmpCM.IsPreferred; 
       } 
       else 
       { 
        dbRecipient.ContactMethods.Add(tmpCM); 
       } 
      } 

      //Only update this if it has changed. 
      if (dbRecipient.LastModifiedBy.UserGUID != myRecipient.LastModifiedBy.UserGUID) 
      { 
       dbRecipient.LastModifiedBy = myRecipient.LastModifiedBy; 
      } 

      dbRecipient.LastModifiedOn = myRecipient.LastModifiedOn; 
     } 
    } 

    context.SaveChanges(); 
} 

Die entsprechenden Klassen:

Benutzer:

public class User 
    { 
     [Key] 
     public Guid UserGUID { get; set; } 

     public string UserName { get; set; } 

     public string FirstName { get; set; } 

     public string LastName { get; set; } 

     public string Email { get; set; } 

     public bool IsSiteAdmin { get; set; } 

     public bool IsActive { get; set; } 

     public DateTime? CreatedOn { get; set; } 

     public DateTime? LastLogin { get; set; } 
    } 

Empfänger:

public class Recipient 
    { 
     [Key] 
     public Guid RecipientGUID { get; set; } 

     [Required(ErrorMessage = "Please enter a Recipient's First Name.")] 
     public string FirstName { get; set; } 

     [Required(ErrorMessage = "Please enter a Recipient's Last Name.")] 
     public string LastName { get; set; } 

     public string Company { get; set; } 

     public UserGroup Owner { get; set; } 

     public virtual ICollection<ContactMethod> ContactMethods { get; set; } 

     public User CreatedBy { get; set; } 

     public DateTime CreatedOn { get; set; } 

     public User LastModifiedBy { get; set; } 

     public DateTime LastModifiedOn { get; set; } 

     public bool IsActive { get; set; } 
    } 

Kontakt Methoden:

public class ContactMethod 
    { 
     [Key] 
     [HiddenInput(DisplayValue = false)] 
     public Guid ContactMethodGUID { get; set; } 

     [ForeignKey("ContactMethodTypeGUID")] 
     public virtual ContactMethodType Type { get; set; } 

     public string CountryCode { get; set; } 

     [Required] 
     public string Identifier { get; set; } 

     public bool IsPreferred { get; set; } 

     [ForeignKey("RecipientGUID")] 
     public virtual Recipient Owner { get; set; } 
    } 

Dieses Problem tritt auf, wenn ich einen Empfänger aktualisieren mag, und es ist ein anderer Benutzer die Aktualisierung zu tun. Also sagen Benutzer abcd hat das letzte Update, aber jetzt aktualisiert Benutzer zyx den Datensatz. So wird die Recipeint.LastUpdatedBy auf den aktuellen Sitzungsbenutzer eingestellt. Wenn ich das mache, bekomme ich den obigen Fehler. Ich kann nicht herausfinden, wie ich darüber hinaus komme.

Eine kleine Anmerkung: wenn ich hinzufügen:

context.Entry(myRecipient.LastModifiedBy).State = EntityState.Unchanged; 

in der

Anweisung if (dbRecipient.LastModifiedBy.UserGUID != myRecipient.LastModifiedBy.UserGUID)

und sagen Benutzer lastModifiedBy an Benutzer abc gesetzt. Jetzt aktualisiert Benutzer asfg diesen Empfänger zum ersten Mal, es geht durch, und LastModifiedBy wird auf Benutzer asfg gesetzt, aber sagen Benutzer abc geht zurück und ändert den Empfänger erneut, so dass lastmodifiedby zurück zu abc geht, es schlägt fehl, mit dem gleichen Fehler .

das macht mich verrückt und ich kann es nicht herausfinden !!!

+0

Sind Sie Dependency Injection mit? Es könnte sein, dass Sie die Klasse verwendet haben, in der 'SaveRecipient' definiert ist, als Singleton? Es sollte "Scoped" sein, so dass Sie pro Anfrage einen Kontext haben. –

+0

Ja, ich bin. Danke, ich werde es mir ansehen. – MarekT

+0

Also meine Empfänger-Klasse enthält zwei Benutzerfelder. Eine für CreatedBy und die andere für LastModifiedBy. Wenn diese auf denselben Benutzer eingestellt sind, erhalte ich diesen Fehler. Ich denke nicht, dass mit meinem Modell etwas nicht stimmt, ich meine, es macht Sinn, es so zu organisieren. – MarekT

Antwort

1

Ich habe die Antwort darauf von Arthur Vickers bei Microsoft. Ich wollte teilen.

Der Code, der die Navigationseigenschaft dbRecipient.LastModifiedBy festlegt, setzt es auf eine Entitätsinstanz, die nicht vom Kontext überwacht wird. Es scheint, als würde der Kontext in diesem Fall bereits eine andere Instanz für dieselbe Entität verfolgen - vermutlich, weil sie durch die Abfrage mit der Navigation CreatedBy eingefügt wurde.
EF kann zwei Instanzen derselben Entität nicht verfolgen, weshalb die Ausnahme ausgelöst wird. Daher müssen Sie EF hier zusätzliche Informationen geben, um zu wissen, was zu tun ist. Dies kann im allgemeinen kompliziert sein.
Beispiel: Wenn die überwachte Instanz über Eigenschaften verfügt, die in der anderen Instanz geändert wurden. Jedoch
, das ist nicht der Fall unter der Annahme, dann können Sie nur die Instanz Nachschlag, der verfolgt wird, und verwenden Sie es stattdessen Zum Beispiel:

if (dbRecipient.LastModifiedBy.UserGUID != myRecipient.LastModifiedBy.UserGUID) 
{ 
    dbRecipient.LastModifiedBy = test.Set<User>().Find(myRecipient.LastModifiedBy.UserGUID); 
} 
Verwandte Themen