У меня есть метод, который подписывает пользователя и пытается обновить пользователя, если viewModel
отличается от объекта user
. Поведение, которое я вижу, сбивает с толку.Почему мой метод UpdateAsync (пользователь) не работает в первый раз, заявив, что пользователь не существует?
Каждый раз, когда выполняется метод, если user
ранее не вошли в систему, линия await _userManager.UpdateAsync(user);
терпит неудачу за исключением: "There is no user with id: 99"
(или любой другой id
значение). Однако, если user
был зарегистрирован, линия работает.
Так, например,
- Пользователь запускает приложение (в настоящее время не вошли в систему) и нажимает кнопку, чтобы получить возможность отправлять
viewModel
к серверу. - приложение регистрирует
user
в, - Если
viewModel
отличается от существующих данныхuser
«s, сервер пытается обновить его. - Это обновление не удастся с
"There is no user with id: 99"
- Пользователь снова нажимает кнопку и отправляет на сервер одни и те же данные. (На этот раз
user
было зарегистрировано в с предыдущей неудачной пост) viewModel
по-прежнему отличается от существующих данных (помните, обновление не удалось в прошлый раз)await _userManager.UpdateAsync(user);
работ и запись обновляется.
Ниже приведен метод:
[UnitOfWork]
public async Task<AjaxResponse> Post(MyViewModel viewModel)
{
try
{
var loginResult = await _userManager.LoginAsync(viewModel.UserName, viewModel.Password, viewModel.TenancyName);
User user;
if (loginResult.Result == AbpLoginResultType.Success)
{
await SignInAsync(loginResult.User, loginResult.Identity);
user = loginResult.User;
if (user.AccessToken != viewModel.AccessToken)
{
user.AccessToken = viewModel.AccessToken;
// why does this fail the first time?
await _userManager.UpdateAsync(user);
}
}
else
{
/* do some other UnitOfWork stuff below */
}
return new AjaxResponse(new MyResult
{
Name = user.Name + " " + user.Surname,
UserName = user.UserName,
EmailAddress = user.EmailAddress,
IsActive = user.IsActive,
Success = true,
UserId = user.UserId,
});
}
catch (Exception ex)
{
throw new HttpException((int)HttpStatusCode.InternalServerError, ex.Message);
}
}
Я могу подтвердить, что пользователь с идентификатором 99 делает на самом деле существует в базе данных.
Для записи, следующее содержание ex.StackTrace
at Abp.Authorization.Users.AbpUserManager`3.<GetUserByIdAsync>d__5b.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Abp.Authorization.Users.AbpUserManager`3.<UpdateAsync>d__64.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at MyProject.Web.Controllers.Api.AccountApiController.<Post>d__16.MoveNext() in C:\dev\MyProject\MyProject.Web\Controllers\Api\AccountApiController.cs:line 146
Я думаю, один ключ может быть в следующем запросе (перехвачено с SQL Server Profiler), который запускается на выполнение перед обновлением:
exec sp_executesql N'SELECT TOP (1)
[Extent1].[Id] AS [Id],
[Extent1].[AccessToken] AS [AccessToken],
[Extent1].[UserId] AS [UserId],
[Extent1].[EmailAddress] AS [EmailAddress],
[Extent1].[TenantId] AS [TenantId],
[Extent1].[IsDeleted] AS [IsDeleted],
-- irrelevant stuff removed
FROM [dbo].[AbpUsers] AS [Extent1]
WHERE
((([Extent1].[TenantId] IS NULL) AND (@DynamicFilterParam_1 IS NULL))
OR (([Extent1].[TenantId] IS NOT NULL) AND ([Extent1].[TenantId] = @DynamicFilterParam_1))
OR (@DynamicFilterParam_2 IS NOT NULL)) AND (([Extent1].[IsDeleted] = @DynamicFilterParam_3)
OR (@DynamicFilterParam_4 IS NOT NULL)) AND ([Extent1].[EmailAddress] = @p__linq__0)',
N'@DynamicFilterParam_1 int,@DynamicFilterParam_2 bit,@DynamicFilterParam_3 bit,@DynamicFilterParam_4 bit,@p__linq__0 nvarchar(4000)'
,@DynamicFilterParam_1=NULL,@DynamicFilterParam_2=NULL,@DynamicFilterParam_3=0,@DynamicFilterParam_4=NULL,@p__linq__0=N'[email protected]'
Здесь мы можем видеть, что @DynamicFilterParam_1=NULL
. Переменная @DynamicFilterParam_1
соответствует значению для [Extent1].[TenantId]
. Если я вручную присвою значение 2
(которое является значением, связанным с записью в db) вместо NULL
и повторит запрос, он возвращает запись, как я ожидаю.
Когда я выполнить метод во второй раз, я вижу, что TenantId правильно присваивается значение 2.
Почему значение, соответствующее TenantId быть назначен NULL в первый раз? Почему метод UpdateAsync
терпит неудачу каждый раз? Что я могу сделать, чтобы он работал?
В ответ на просьбу ниже, определение UpdateAsync доступен в the asp.net boilerplate github
пожалуйста вывесить код UpdateAsync – Viru
Я добавил ссылку на источник UpdateAsync. Это на GitHub. – DaveDev
Привет, @DaveDev, сейчас я сталкиваюсь с той же проблемой. Вы нашли решение случайно? – Vlad