Я Увеличенная ApplicationUser, добавив родительский объект:OptimisticConcurrencyException при удалении ApplicationUser, который имеет родителя
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; }
}
и связанный с ним DbContext ссылку на новой сущности
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public DbSet<Master> Masters { get; set; }
}
Теперь, когда я попробуйте удалить ApplicationUser, userManager.UpdateAsync()
выдает OptimisticConcurrencyException
.
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>();
}
Чтобы повторить, у моей модели данных нет элементов для проверки параллелизма. Вышеупомянутый код вырезается и вставляется из недавно созданного приложения MVC, которое я изменил, добавив родительский объект в объект ApplicationUser.
Другое примечание: при исследовании этой проблемы я столкнулся с SO-сообщением (которое я не могу найти сейчас) с нескольких лет назад, которое утверждало, что это известная ошибка, так как Identity запутывается, когда пытается обновить и видит, что ничего (в родительской записи) не изменилось.
И еще одно примечание. Я попытался сделать внешний ключ MasterId
нулевым и установить его значение null перед тем, как попытаться удалить пользователя. Не помогло. Проблема заключается в наличии внешнего ключа в объекте ApplicationUser
, независимо от того, имеет ли значение FK значение.
Вопрос: Почему вы делаете «UpdateAsync (user)» _after_ 'DeleteAsync (user)'? На самом деле, почему вы вообще называете «Update»? –
@ ChrisCurtis Darned хороший вопрос, нет хорошего ответа. По какой-то причине я понял, что 'Delete (user)' работал как 'context.Users.Remove (user)', который не сохраняется в базе данных до тех пор, пока вы не назовете 'context.SaveChanges()'. Если вы будете так любезны, чтобы опубликовать свой комментарий в качестве ответа, я соглашусь с ним. Благодаря! –
Таким образом, возникает очевидный вопрос: в каких сценариях мне нужно вызвать 'userManager.Update()'? «Документация» («Обновляет пользователя») совершенно бесполезна. Выполняют ли все подпрограммы UserManager свои изменения? Если я изменю свойства UserName или Email в объекте ApplicationUser, могу ли я просто вызвать DbContext.SaveChanges() или UserManager.Update сделать какую-то другую магию? Я думаю, все это было бы большим кормом для нового вопроса SO ... –