ASP.NET核心身份.使用ApplicationDbContext和UserManager.他们是否分享背景?

Mor*_*goZ 5 c# asp.net-identity asp.net-core

我在ASP.NET MVC Core 2应用程序中有一个数据库初始化方法.在该方法中,我使用ApplicationDbContext和UserManager来初始化数据库.我从构造函数的依赖注入中获取了两个实例:

public static void Initialize(ApplicationDbContext context,
            UserManager<ApplicationUser> user)
Run Code Online (Sandbox Code Playgroud)

我想知道的是,如果它们共享相同的上下文实例,或者为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();
Run Code Online (Sandbox Code Playgroud)

在CreateAsync调用之后,用户在数据库中创建.

但是,如果那时我像这样更新用户:

adminTeacherUser.Name = "other";                
userManager.UpdateAsync(adminTeacherUser);
Run Code Online (Sandbox Code Playgroud)

调用UpdateAsync后,数据库中不会更新任何内容.用户名仍然是"测试".

但是,如果那时我执行:

context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

将应用更改并更新数据库.

那么,为什么CreateAsync方法"保存其更改"而不显式调用"context.SaveChanges"并且UpdateAsync方法需要它?ApplicationDbContext实例是通过依赖注入得到的,与CreateAsync使用的相同吗?

谢谢.

SO *_*ood 7

ASP.NET Core应用程序中的Entity Framework Core的默认注册是按请求范围,因此它们将明确地共享上下文.

正如您可以从EF Core for ASP.NET Core Identity的默认实现的源代码中看到的(这里

/// <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;
}
Run Code Online (Sandbox Code Playgroud)

/// <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;
}
Run Code Online (Sandbox Code Playgroud)

,他们都保存了变化.

您遇到的问题是您没有await获得结果UpdateAsync,因此您需要更改为:

await userManager.UpdateAsync(adminTeacherUser);
//or
userManager.UpdateAsync(adminTeacherUser).Wait();
Run Code Online (Sandbox Code Playgroud)

当然,使用async-all-the-way是首选版本,您不应该阻止使用.Wait().