2016-12-16 5 views
1

Ich versuche, meine Userroles Tabelle zu aktualisieren, aber es wird nicht aktualisiert. Ich versuche, zwei Dinge zu aktualisieren: 1. die E-Mail 2. die Benutzerrolle. Da das Update in 2 Tabellen erfolgen muss, verwende ich zwei separate Befehle. Wenn ich das Update auf der E-Mail allein (Benutzer) ausführen, funktioniert es, aber wenn ich die Rolle (AspUserRoles) aktualisiere, tut es nichts. Wenn ich beides ausführe, funktioniert es auch nicht, weil UserRoles.Attach (userRole) die Aktualisierung verhindert. Ich bekomme auch keine Fehler.Kann nicht mit .Attach() aktualisieren

überprüfte ich, wenn ApplicationRole.Id und ApplicationUser.Id einen Wert hat, und es macht den Wert zurück, ich will.

enter image description here

Hier ist mein UserController.cs:

public async Task<IActionResult> Edit(UserViewModel model, Guid id) 
{ 
    var alert = new Alert(); 

    try 
    { 
     if(!ModelState.IsValid) 
     { 
      alert.Message = alert.ExceptionMessage = ApplicationDbContextMessage.INVALID; 
      throw new Exception(); 
     }  


     var originalModel = ApplicationDbContext.Users.FirstOrDefault(u => u.Id == id);  
     var userRole = ApplicationDbContext.UserRoles.FirstOrDefault(i => i.UserId == id); 


     if(originalModel == null) 
     { 
      alert.Message = alert.ExceptionMessage = ApplicationDbContextMessage.NOTEXISTS; 
      throw new Exception(); 

     } 


     originalModel.Email = model.ApplicationUser.Email; 

     userRole.RoleId = model.ApplicationRole.Id; 


     ApplicationDbContext.Users.Attach(originalModel); 
     ApplicationDbContext.UserRoles.Attach(userRole); 


     ApplicationDbContext.Entry(originalModel).State = EntityState.Modified; 


     if (await ApplicationDbContext.SaveChangesAsync() == 0) 
     { 
      alert.Message = alert.ExceptionMessage = ApplicationDbContextMessage.EDITNOK; 
      throw new Exception(); 
     } 

     alert.Message = ApplicationDbContextMessage.EDITOK; 
     return RedirectToAction("Index"); 
    } 
    catch(Exception ex) 
    { 
     alert.Type = AlertType.Error; 
     alert.ExceptionMessage = ex.Message; 

     model = await ViewModel(model.ApplicationUser); 

     ModelState.AddModelError(string.Empty, alert.ExceptionMessage); 
    } 
    return View(model); 
} 
+1

Sie sollten nicht aufrufen müssen 'Attach' für diese Objekte, werden sie aus dem gleichen Zusammenhang kommen sie gespeichert sind, und sie nie die Verbindung unterbrochen wird. Hast du das probiert, ohne "Attach" oder "EntityState" zu nennen? –

+0

Ich habe und es funktioniert nicht. Als ich hinzufügen kann (Userrole) statt Attach (Userrole) es hat eine neue Zeile in der Tabelle Userrole hinzufügen, aber dann habe ich eine dublicate mit dem gleichen Benutzer-ID ... – hxwtch

+0

Sie brauchen nicht 'Add' entweder zu nennen. Ändern Sie einfach die Eigenschaften und rufen Sie SaveChanges im Kontext auf. Sie sollten in der Lage sein, Ihren ursprünglich geposteten Code zu übernehmen, die 2 Zeilen, die 'Attach' sagen, und die Zeile, die den' State' ändert, zu entfernen. –

Antwort

2

Die Art und Weise Sie die Daten in diesem Code modifizieren, müssen Sie nicht Attach oder Add auf der Context nennen es wissen zu lassen Änderungen an Entitäten, das wird automatisch passieren.

Sobald Sie ein Objekt aus einem DbSet des DbContext ziehen, wird es von diesem DbContext verfolgt (angehängt). Wenn Sie SaveChanges auf der DbContext nennen es keine Einheiten scannen, die sie verfolgt, die aktuellen Werte des alten Werte zu vergleichen, Änderungen zu finden. Diese Änderungen werden dann an die Datenbank gesendet.

Sie sollten buchstäblich in der Lage sein, drei Zeilen Code zu entfernen, von dem, was Sie ursprünglich gebucht und haben sie funktionieren.

... 
originalModel.Email = model.ApplicationUser.Email; 
userRole.RoleId = model.ApplicationRole.Id; 

ApplicationDbContext.Users.Attach(originalModel); // <--- Delete this line 
ApplicationDbContext.UserRoles.Attach(userRole); // <--- Delete this line 
ApplicationDbContext.Entry(originalModel).State = EntityState.Modified; // <--- Delete this line 

if (await ApplicationDbContext.SaveChangesAsync() == 0) 
... 

Ein wenig etwas anderes bemerkte ich. Es sieht so aus, als ob Sie eine einzige DbContext Instanz für die gesamte Anwendung verwenden. Dies wird normalerweise als "Anti-Patern" im Entity Framework betrachtet. Sie sollten eine neue DbContext Instanz (mit using) für jede "logische" Operation erstellen, die Sie ausführen. Diese Instanz sollte nur für das Leben dieser Operation am Leben sein.

In MVC ist dies normalerweise eine DbContext Instanz pro ActionMethod.