Подтвердить что ты не робот

SQL-запись в таблицу пользователей ASP.NET не сохраняется

Моя настройка:

  • ASP.NET 4.5 web api (на Azure), сохраняющий данные в SQL db (также на Azure)
  • Веб-интерфейс AngularJS (другой веб-сайт Azure)

Когда пользователь сначала регистрируется, я показываю им "вводное начало". Вступление должно запускаться только один раз - я регистрирую временную метку даты запуска ввода в качестве настраиваемого поля в пользовательской таблице ASP.NET.

Представьте себе мое удивление, когда я вхожу в систему (как пользователь) и вижу вступление TWICE.

Передняя часть AngularJS правильно отправляет сообщение "intro view" на ASP.NET api, и api отвечает сообщением об успешном завершении. Однако, когда я смотрю на необработанные данные в db, метка времени определенно НЕ обновляется. Следовательно, пользователь увидит ввод еще раз (в какой момент метка времени записывается в db должным образом).

У меня дерьмовое обходное решение. После того как клиент запрашивает токен маркера OAuth с моего сервера, клиент затем запрашивает информацию пользователя (чтобы решить, показывать или не показывать тур). Ожидание 100 мс, а затем отправка сообщения "Просмотр тура" обратно на сервер маскирует проблему.

Я не видел ЛЮБЫХ других проблем хранения данных в любой момент. Поскольку наш db находится на Azure, я не могу подключить Profiler, и встроенный аудит не дает мне никаких подсказок.

Есть ли что-то о запросе маркера, который оставляет ASP.NET-идентификатор в смешном состоянии? И требуется короткое ожидание, прежде чем вы сможете написать в таблицу? Являются ли настраиваемые поля, которые расширяют базовую настройку Identity, подверженной таким проблемам? Может ли UserManager делать что-то странное в своем черном ящике?

Есть ли у кого-нибудь предложения по продолжению отладки этой проблемы? Или когда-либо слышал о чем-то подобном?

Вот соответствующий код, который должен обновлять временную метку "просмотр тура" в db:

    [HttpPost, Route("UserInfo")]
    public async Task<IHttpActionResult> UpdateUserInfo(UpdateBindingModel model)
    {
        var currentUser = UserManager.FindById(User.Identity.GetUserId());

        if (model.FirstName != null)
        {
            currentUser.FirstName = model.FirstName;
        }
        if (model.LastName != null)
        {
            currentUser.LastName = model.LastName;
        }
        if (model.SetIntroViewCompleteDate)
        {
            currentUser.IntroViewCompleteDate = DateTime.UtcNow;
        }
        if (model.SetIntroViewLaunchDate)
        {
            currentUser.IntroViewLaunchDate = DateTime.UtcNow;
        }
        if (model.SetTipTourCompleteDate)
        {
            currentUser.TipTourCompleteDate = DateTime.UtcNow;
        }
        if (model.SetTipTourLaunchDate)
        {
            currentUser.TipTourLaunchDate = DateTime.UtcNow;
        }

        IdentityResult result = await UserManager.UpdateAsync(currentUser);
        if (result.Succeeded)
        {
            var data = new UserInfoViewModel
            {
                FirstName = currentUser.FirstName,
                LastName = currentUser.LastName,
                IntroViewLaunchDate = currentUser.IntroViewLaunchDate
            };

            return Ok(data);
        }

        return InternalServerError();
    }

ОБНОВЛЕНИЕ ********* 4/18

Я также попытался полностью отойти от материалов UserManager. Я пробовал следующие изменения (вытаскивание пользовательских данных из таблицы, как я хотел бы получить доступ к любым другим данным), но он по-прежнему ведет себя одинаково. Я начинаю думать, что размещение пользовательских полей в объекте ApplicationUser - плохая идея...

Новое извлечение и сохранение db выглядит следующим образом:

 ApplicationDbContext newContext = new ApplicationDbContext();
 var currentUser = await (from c in newContext.Users
                          where c.Email == User.Identity.Name
                          select c).SingleOrDefaultAsync();

 //update some values

 await newContext.SaveChangesAsync();
4b9b3361

Ответ 1

Хорошо, вот что я сделал, чтобы решить проблему. Я полностью отключил свои пользовательские данные от встроенных компонентов идентификации ASP.NET. Теперь у меня есть отдельный объект (и, следовательно, отдельная таблица SQL), в котором хранятся такие вещи, как FirstName, LastName, LastActiveDate и т.д. И т.д.

Это решило мою проблему полностью, хотя в некоторых ситуациях она ввела другой вызов в базу данных. Я считал, что это не большая проблема с производительностью, о которой нужно беспокоиться. Мне осталось думать, что это было какое-то странное состояние гонки, связанное с генерацией токена для пользователя с идентификатором ASP.NET, а затем быстро записывая базу данных Azure SQL - лорд знает, что именно в моем коде вызвало эту проблему.

Если у вас есть проблема, которую трудно решить, часто лучший план - это изменить проблему.

Теперь мне нужно найти мета-поток, обсуждая, что делать с пунктами баунти, когда вы взорвали проблему...

Ответ 2

В основном проблема может заключаться в инициализации `UserManager 'и в том, что этот класс работает в контексте db, поэтому вам нужно сохранить изменения в этом контексте. Вот пример:

var userStore = new UserStore<ApplicationUser>(new MyDbContext());
var userManager = new UserManager(userStore);

Таким образом вы помните как менеджера, так и контекста. Затем в вашем методе вы обычно вызываете:

IdentityResult result = await userManager.UpdateAsync(currentUser);

а затем сохранение этого изменения в контексте db:

var dbContext = userStore.context;
dbContext.saveChanges();

Ответ 3

На основании вашего комментария, что ожидание 100 мс маскирует проблему, я думаю, что у вас может возникнуть проблема с многочисленными асинхронными вызовами ожидания. Попробуйте синхронно запускать вызовы и посмотрите, есть ли у вас такая же проблема. Я предполагаю, что проблема может исчезнуть. Мой опыт заключается в том, что использование async-ожидания может быть сложным, если вы вызываете асинхронные методы, которые вызывают другие асинхронные методы. У вас может быть код, который выполняется без правильных результатов.