2016-05-04 3 views
0

ich ApplicationUser verlängert habe durch eine übergeordnete Entität hinzu:OptimisticConcurrencyException beim Löschen eines ApplicationUser, die einen Elternteil hat

public class ApplicationUser : IdentityUser 
{ 
    public int MasterId { get; set; } 
    public virtual Master Master { get; set; } 
} 

public class Master 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

und die damit verbundene DbContext Verweis auf die neue Einheit

public class ApplicationDbContext : IdentityDbContext<ApplicationUser> 
{ 
    public DbSet<Master> Masters { get; set; } 
} 

Nun, wenn ich Versuchen Sie, einen ApplicationUser zu löschen, userManager.UpdateAsync() löst einen aus.

public class HomeController : Controller 
{ 
    public async Task<ActionResult> Index() 
    { 
     // Get the DbContext and UserManager out of the OWIN pipeline 
     var db = GetDbContext(this); 
     var userManager = GetUserManager(this); 

     // Create a Master record if necessary 
     if (db.Masters.Count() == 0) { 
      db.Masters.Add(new Master { Name = "The Master" }); 
      await db.SaveChangesAsync(); 
     } 

     var masterId = (from m in db.Masters select m.Id).First(); 

     // Create a new ApplicationUser 
     var user = new ApplicationUser { 
      UserName = "Bob", 
      Email = "[email protected]", 
      MasterId = masterId 
     }; 

     await userManager.CreateAsync(user, "Password123?"); 
     await userManager.UpdateAsync(user); 

     // Try to delete the ApplicationUser 
     user = (from u in db.Users select u).First(); 
     await userManager.DeleteAsync(user); 
     await userManager.UpdateAsync(user); // Throws OptimisticConcurrencyException 

     return View(); 
    } 

    public static ApplicationDbContext GetDbContext(Controller controller) 
    { 
     return controller.HttpContext.GetOwinContext() 
       .Get<ApplicationDbContext>(); 
    } 

    public static ApplicationUserManager GetUserManager(Controller controller) 
    { 
     return controller.HttpContext.GetOwinContext() 
       .GetUserManager<ApplicationUserManager>(); 
    } 

Nur um zu wiederholen, mein Datenmodell hat keine Gleichzeitigkeitsprüfung Mitglieder. Der obige Code wird aus einer neu erstellten MVC-Anwendung ausgeschnitten und eingefügt, die ich durch Hinzufügen einer übergeordneten Entität zur ApplicationUser-Entität geändert habe. Ein weiterer Hinweis: Bei der Untersuchung dieses Problems stieß ich auf einen SO - Post (den ich jetzt nicht finden kann), der behauptete, dass dies ein bekannter Bug sei, denn Identity wird verwirrt, wenn er versucht, das Update zu aktualisieren verwandte Datensätze und sieht, dass sich nichts (im übergeordneten Datensatz) geändert hat.

Und noch ein Hinweis: Ich habe versucht, die MasterId Fremdschlüssel Nullwert, und setzen Sie es auf Null, bevor Sie versuchen, den Benutzer zu löschen. Hat nicht geholfen. Das Problem scheint das Vorhandensein des Fremdschlüssels in der Einheit ApplicationUser zu sein, unabhängig davon, ob der FK einen Wert hat oder nicht.

+0

Frage: Warum machst du 'UpdateAsync (Benutzer)' _after_ 'DeleteAsync (Benutzer)'? In der Tat, warum nennst du 'Update' überhaupt? –

+0

@ChrisCurtis Darned gute Frage, keine gute Antwort. Aus irgendeinem Grund habe ich es mir in den Kopf gesetzt, dass 'Delete (user)' wie 'context.Users.Remove (user)' funktioniert, das nicht in der Datenbank persistiert wird, bis man 'context.SaveChanges()' aufruft. Wenn Sie Ihren Kommentar als Antwort posten würden, akzeptiere ich ihn. Vielen Dank! –

+0

Das wirft also die naheliegende Frage auf: In welchen Szenarien muss ich 'userManager.Update()' aufrufen? Die "Dokumentation" ("Aktualisiert einen Benutzer.") Ist völlig wertlos. Behalten alle UserManager-Routinen ihre Änderungen bei? Wenn ich die Eigenschaften UserName oder Email in meiner ApplicationUser-Entität ändere, kann ich dann DbContext.SaveChanges() aufrufen oder macht UserManager.Update noch etwas anderes? Ich denke, das alles wäre ein großartiges Futter für eine neue SO-Frage ... –

Antwort

0

Der Anruf an UpdateAsync(user) wird nicht benötigt und verursacht wahrscheinlich Ihr Problem nach der DeleteAsync(user), seit der Benutzer gelöscht wurde. Entfernen Sie die Update-Anrufe und Sie sollten gut sein

+0

War nur so, wie OP angefordert. Ich werde es ändern, um mehr Antwort wie zu sein –

Verwandte Themen