我在 ASP.NET MVC Core 2应用程序中有一个数据库初始化方法。 在该方法中,我使用ApplicationDbContext和UserManager来初始化数据库。 我从构造函数的依赖项注入中获取两个实例:
public static void Initialize(ApplicationDbContext context,
UserManager<ApplicationUser> user)
我想知道的是它们是否共享相同的上下文实例,或者是否为ApplicationDbContext创建了一个上下文,为UserManager创建了另一个上下文。 如果我执行这样的事情:
ApplicationUser adminTeacherUser = new ApplicationUser
{
UserName = "test@test.com",
Email = "test@test.com",
EmailConfirmed = true,
Name = "test",
LastName = "test",
BirthDate = null,
EntryDate = DateTime.Now
};
userManager.CreateAsync(adminTeacherUser, "password").Wait();
用户是在创建异步调用后立即在数据库中创建的。
但是,如果那时我像这样更新用户:
adminTeacherUser.Name = "other";
userManager.UpdateAsync(adminTeacherUser);
调用 UpdateAsync 后,数据库中不会更新任何内容。正在"测试"的用户的名称。
但是,如果那时我执行:
context.SaveChanges();
将应用更改并更新数据库。
那么,为什么 CreateAsync 方法"保存其更改"而不显式调用"上下文"。保存更改"和更新异步方法需要它吗?我通过依赖注入获得的应用程序数据库上下文实例是否与 CreateAsync 使用的相同?
谢谢。
ASP.NET Core 应用程序中实体框架核心的默认注册是每个请求的范围,因此它们将最终共享上下文。
从用于 ASP.NET 核心标识的 EF Core 的默认实现的源代码中可以看到(此处
/// <summary>
/// Creates the specified <paramref name="user"/> in the user store.
/// </summary>
/// <param name="user">The user to create.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation, containing the <see cref="IdentityResult"/> of the creation operation.</returns>
public async override Task<IdentityResult> CreateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
Context.Add(user);
await SaveChanges(cancellationToken);
return IdentityResult.Success;
}
和这里
/// <summary>
/// Updates the specified <paramref name="user"/> in the user store.
/// </summary>
/// <param name="user">The user to update.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation, containing the <see cref="IdentityResult"/> of the update operation.</returns>
public async override Task<IdentityResult> UpdateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
Context.Attach(user);
user.ConcurrencyStamp = Guid.NewGuid().ToString();
Context.Update(user);
try
{
await SaveChanges(cancellationToken);
}
catch (DbUpdateConcurrencyException)
{
return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure());
}
return IdentityResult.Success;
}
,它们都会保存更改。
您遇到的问题是您没有await
UpdateAsync
的结果,因此您需要更改为:
await userManager.UpdateAsync(adminTeacherUser);
//or
userManager.UpdateAsync(adminTeacherUser).Wait();
当然,使用异步方式是首选版本,您不应该阻止使用.Wait()
.