使用异步任务方法处理DbContext

时间:2018-08-01 05:20:13

标签: c# angularjs asp.net-web-api async-await

我当前正在使用异步Task方法来实现IAuthenticationFilter接口。成功登录后,我将尝试访问具有此属性的API,它将正常工作。但是,一旦我返回并再次访问API,就会抛出异常。

public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
    var token = context.Request.Headers.Authorization.Parameter;
    var principal = await AuthenticateToken(token)
    // Other code here ... 
}

protected Task<IPrincipal> AuthenticateToken(string token)
{
    var secretKey = _authenticationBusiness.GetSecretKey(); // error triggers here.

    if (principal == null)
        context.ErrorResult = new AuthenticationFailureResult("Invalid token", request);
    else
        context.Principal = principal;
}

//AuthenticationBusiness.cs
public string GetSecretKey()
{
    using (_unitOfWork)
    {
        var token = _unitOfWork.Tokens.GetToken();

        return token.SecretKey ?? string.Empty;
    }
}

//Dependency Injection using Unity
    container.RegisterType<IUnitOfWork, UnitOfWork>(new HierarchicalLifetimeManager());
    container.RegisterType<IContext, Context>(new HierarchicalLifetimeManager());

//UnitOfWork.cs
private readonly IContext _context;

public UnitOfWork(IContext context, IJWTRepository tokens)
{
    _context = context;
    Tokens = tokens;
}

public IJWTRepository Tokens { get; private set; }

public void Dispose()
{
    _context.Dispose();
}


//Context.cs
public class Context : DbContext, IContext
{
    public new void SaveChanges()
    {
        base.SaveChanges();
    }

    public new void Dispose()
    {
        base.Dispose();
    }
}

//JWTRepository.cs
public class JWTRepository : Repository<JsonWebToken>, IJWTRepository
{
    public JWTRepository(Context context) : base(context) { }

    public JsonWebToken GetToken()
    {
        return Context.Tokens
            .OrderBy(jwt => jwt.Id)
            .Take(1)
            .SingleOrDefault();
    }

    private Context Context => _context as Context;
}

如果我尝试删除此属性并多次访问API,那么不会发生任何错误,因此我认为这与该属性具有异步方法有关吗?

2 个答案:

答案 0 :(得分:2)

  

当IDisposable对象的生存期限制为单个时   方法,您应该在using语句中声明并实例化它。   using语句在对象中的对象上调用Dispose方法。   正确的方式,并且(当您如前所述使用时)也会导致   调用Dispose时,对象本身将超出范围。中   using块,该对象是只读的,无法修改,或者   重新分配。

using Statement (C# Reference)

在您的代码中,问题在于您将GetSecretkey()包装到using()中,这将处置_unitOfWork,并且当您再次尝试访问它时将显示错误。

希望此代码对您有用。

//AuthenticationBusiness.cs

public string GetSecretKey()
{
    var token = _unitOfWork.Tokens.GetToken();

    return token.SecretKey ?? string.Empty;
}

答案 1 :(得分:0)

函数AuthenticateToken中的问题。使用async-await时,如果Task处理了项目,请确保在返回之前先等待每个Task。参见what is the purpose of return await。第一个答案集中在一次性物品上

我假设您省略了方法AuthenticateToken的某些部分,因为我没有说返回值。

解决方案:声明方法async,并在返回之前等待Task

async Task<IPrincipal> AuthenticateToken(string token)
{
    var secretKey = _authenticationBusiness.GetSecretKey(); 
    ...
    // Somewhere there is a Task involved, 
    Task<IPrincipal> myTask = ...

    // instead of return myTask:
    return await myTask;
}