C# 为什么我的UpdateAsync(user)方法第一次失败,声称用户没有';不存在?
如果C# 为什么我的UpdateAsync(user)方法第一次失败,声称用户没有';不存在?,c#,entity-framework,asp.net-boilerplate,C#,Entity Framework,Asp.net Boilerplate,如果viewModel与user对象不同,我有一种方法可以让用户登录并尝试更新用户。我看到的行为令人困惑 每次执行该方法时,如果用户之前未登录,则行wait\u userManager.UpdateAsync(用户)失败,例外情况是:“没有id为99的用户”(或任何id值)。但是,如果用户以前登录过,则该行可以工作 那么比如说, 用户启动应用程序(当前未登录)并单击按钮将viewModel发布到服务器 应用程序将用户记录在 如果viewModel与现有用户的数据不同,服务器将尝试更新该数据 此更
viewModel
与user
对象不同,我有一种方法可以让用户登录并尝试更新用户。我看到的行为令人困惑
每次执行该方法时,如果用户
之前未登录,则行wait\u userManager.UpdateAsync(用户)代码>失败,例外情况是:“没有id为99的用户”
(或任何id
值)。但是,如果用户以前登录过,则该行可以工作
那么比如说,
用户启动应用程序(当前未登录)并单击按钮将viewModel
发布到服务器李>
应用程序将用户
记录在
如果viewModel
与现有用户的数据不同,服务器将尝试更新该数据李>
此更新将失败,因为“没有id为99的用户”
用户再次单击按钮并将相同的数据发布到服务器。(这次用户已从上一次失败的post登录)
viewModel
仍与现有数据不同(请记住,上次更新失败)
wait\u userManager.UpdateAsync(用户)代码>工作并更新记录
方法如下:
[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);
}
}
我认为更新之前执行的以下查询(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'myemail@mail.com'
在这里,我们可以看到@DynamicFilterParam\u 1=NULL
。变量@DynamicFilterParam_1
对应于[Extent1].[TenantId]
的值。如果我手动分配值2
(这是与数据库中的记录相关联的值),而不是NULL
,然后重新运行查询,它将按预期返回记录
当我第二次执行该方法时,我可以看到TenantId被正确地赋值为2
为什么第一次为TenantId对应的值赋值为空?为什么UpdateAsync
方法每次都失败?我能做些什么使它工作
作为对以下请求的响应,UpdateSync的定义在中提供,这是因为多租户。ABP在用户登录之前不知道租户。您应该手动设置租户id以切换到用户的租户。我的登录代码如下:
public virtual async Task<JsonResult> Login(LoginViewModel loginModel, string returnUrl = "", string returnUrlHash = "")
{
var loginResult = await GetLoginResultAsync(loginModel.UsernameOrEmailAddress, loginModel.Password, loginModel.TenancyName);
var tenantId = loginResult.Tenant == null ? (int?)null : loginResult.Tenant.Id;
using (UnitOfWorkManager.Current.SetTenantId(tenantId))
{
if (loginResult.User.ShouldChangePasswordOnNextLogin)
{
loginResult.User.SetNewPasswordResetCode();
return Json(new AjaxResponse
{
TargetUrl = Url.Action(
"ResetPassword",
new ResetPasswordViewModel
{
TenantId = tenantId,
UserId = SimpleStringCipher.Instance.Encrypt(loginResult.User.Id.ToString()),
ResetCode = loginResult.User.PasswordResetCode
})
});
}
var signInResult = await _signInManager.SignInOrTwoFactorAsync(loginResult, loginModel.RememberMe);
if (signInResult == SignInStatus.RequiresVerification)
{
return Json(new AjaxResponse
{
TargetUrl = Url.Action(
"SendSecurityCode",
new
{
returnUrl = returnUrl + (returnUrlHash ?? ""),
rememberMe = loginModel.RememberMe
})
});
}
Debug.Assert(signInResult == SignInStatus.Success);
await UnitOfWorkManager.Current.SaveChangesAsync();
if (string.IsNullOrWhiteSpace(returnUrl))
{
returnUrl = GetAppHomeUrl();
}
if (!string.IsNullOrWhiteSpace(returnUrlHash))
{
returnUrl = returnUrl + returnUrlHash;
}
return Json(new AjaxResponse { TargetUrl = returnUrl });
}
}
公共虚拟异步任务登录(LoginViewModel loginModel,string returnUrl=“”,string returnUrlHash=“”)
{
var loginResult=await GetLoginResultAsync(loginModel.UserName或MailAddress、loginModel.Password、loginModel.TenancyName);
var tenantId=loginResult.Tenant==null?(int?)null:loginResult.Tenant.Id;
使用(UnitOfWorkManager.Current.SetTenantId(tenantId))
{
if(loginResult.User.ShouldChangePasswordOnNextLogin)
{
loginResult.User.SetNewPasswordResetCode();
返回Json(新的AjaxResponse
{
TargetUrl=Url.Action(
“重置密码”,
新的ResetPasswordViewModel
{
TenantId=TenantId,
UserId=SimpleStringCipher.Instance.Encrypt(loginResult.User.Id.ToString()),
ResetCode=loginResult.User.PasswordResetCode
})
});
}
var signInResult=wait _signInManager.signinorTwofactorSync(loginResult,loginModel.RememberMe);
if(signInResult==SignInStatus.RequiresVerification)
{
返回Json(新的AjaxResponse
{
TargetUrl=Url.Action(
“SendSecurityCode”,
新的
{
returnUrl=returnUrl+(returnUrlHash???),
rememberMe=loginModel.rememberMe
})
});
}
Assert(signInResult==SignInStatus.Success);
等待UnitOfWorkManager.Current.SaveChangesSync();
if(string.IsNullOrWhiteSpace(returnUrl))
{
returnUrl=GetAppHomeUrl();
}
如果(!string.IsNullOrWhiteSpace(returnUrlHash))
{
returnUrl=returnUrl+returnUrlHash;
}
返回Json(新的AjaxResponse{TargetUrl=returnUrl});
}
}
关键是使用(UnitOfWorkManager.Current.SetTenantId(tenantId))
语句,这是因为多租户。ABP在用户登录之前不知道租户。您应该手动设置租户id以切换到用户的租户。我的登录代码如下:
public virtual async Task<JsonResult> Login(LoginViewModel loginModel, string returnUrl = "", string returnUrlHash = "")
{
var loginResult = await GetLoginResultAsync(loginModel.UsernameOrEmailAddress, loginModel.Password, loginModel.TenancyName);
var tenantId = loginResult.Tenant == null ? (int?)null : loginResult.Tenant.Id;
using (UnitOfWorkManager.Current.SetTenantId(tenantId))
{
if (loginResult.User.ShouldChangePasswordOnNextLogin)
{
loginResult.User.SetNewPasswordResetCode();
return Json(new AjaxResponse
{
TargetUrl = Url.Action(
"ResetPassword",
new ResetPasswordViewModel
{
TenantId = tenantId,
UserId = SimpleStringCipher.Instance.Encrypt(loginResult.User.Id.ToString()),
ResetCode = loginResult.User.PasswordResetCode
})
});
}
var signInResult = await _signInManager.SignInOrTwoFactorAsync(loginResult, loginModel.RememberMe);
if (signInResult == SignInStatus.RequiresVerification)
{
return Json(new AjaxResponse
{
TargetUrl = Url.Action(
"SendSecurityCode",
new
{
returnUrl = returnUrl + (returnUrlHash ?? ""),
rememberMe = loginModel.RememberMe
})
});
}
Debug.Assert(signInResult == SignInStatus.Success);
await UnitOfWorkManager.Current.SaveChangesAsync();
if (string.IsNullOrWhiteSpace(returnUrl))
{
returnUrl = GetAppHomeUrl();
}
if (!string.IsNullOrWhiteSpace(returnUrlHash))
{
returnUrl = returnUrl + returnUrlHash;
}
return Json(new AjaxResponse { TargetUrl = returnUrl });
}
}
公共虚拟异步任务登录(LoginViewModel loginModel,string returnUrl=“”,string returnUrlHash=“”)
{
var loginResult=await GetLoginResultAsync(loginModel.UserName或MailAddress、loginModel.Password、loginModel.TenancyName);
var tenantId=loginResult.Tenant==null?(int?)null:loginResult.Tenant.Id;
使用(UnitOfWorkManager.Current.SetTenantId(tenantId))
{
if(loginResult.User.ShouldChangePasswordOnNextLogin)
{
loginResult.User.SetNewPasswordResetCode();
返回Json(新的AjaxResponse
{
TargetUrl=Url.Action(
“重置密码”,
新的ResetPasswordViewModel
{
TenantId=TenantId,
UserId=SimpleStringCipher.Instance.Encrypt(loginResult.User.Id.ToString()),
ResetCode=loginResult.User.PasswordResetCode
})
});
}
var signInResult=wait _signInManager.signinorTwofactorSync(loginResult,loginModel.RememberMe);
if(signInResult==SignInStatus.RequiresVerification)
{
返回Json(新的AjaxResponse
{