否定Task <bool>而没有等待?

时间:2019-12-12 16:03:24

标签: c# entity-framework async-await

是否有一种方法可以否定一个返回Task<bool>的函数,而无需使用async / await显式运行该函数?我的FluentValidators中有几项独特的检查。我想做这样的事情:

public Task<bool> HasUniqueNameAsync(Entity entity, string propName, CancellationToken cancellationToken = default(CancellationToken))
{
    return _dbContext.Entities.AnyAsync(x => !(x.PropName == propName && x.Id != entity.Id));
}

但是,LINQ查询不是转换为布尔值,而是转换为

x.PropName != propName && x.Id == entity.Id

这不是等效的。目前,我已经更新了我独特的检查功能,使它们看起来像这样:

public async Task<bool> HasUniqueNameAsync(Entity entity, string propName, CancellationToken cancellationToken = default(CancellationToken))
{
    return !await _dbContext.Entities.AnyAsync(x => x.PropName == propName && x.Id != entity.Id);
}

是否可以在不显式使用async / await的情况下添加否定?

2 个答案:

答案 0 :(得分:3)

您可以返回continuation task,取反AnyAsync任务的结果:

public Task<bool> HasUniqueNameAsync(Entity entity, string propName, CancellationToken cancellationToken = default(CancellationToken))
{
    return _dbContext.Entities
        .AnyAsync(x => x.PropName == propName && x.Id != entity.Id))
        .ContinueWith(continuation => !continuation.Result, cancellationToken );
}

答案 1 :(得分:1)

有一种逻辑方法可以做到这一点。您当前正在检查“是否有任何匹配项”并将其否定-从逻辑上讲,“没有任何匹配项”与“全部不匹配”是同一回事。因此,如果您当前的代码是:

public async Task<bool> HasUniqueNameAsync(Entity entity, string propName, CancellationToken cancellationToken = default(CancellationToken))
{
    return !await _dbContext.Entities.AnyAsync(x => x.PropName == propName && x.Id != entity.Id);
}

然后您可以通过执行以下操作将否定项移入函数中:

public Task<bool> HasUniqueNameAsync(Entity entity, string propName, CancellationToken cancellationToken = default(CancellationToken))
{
    return _dbContext.Entities.AllAsync(x => !(x.PropName == propName && x.Id != entity.Id));
}

或者,您可以使用延续来对要完成的任务执行的操作附加操作:

public async Task<bool> HasUniqueNameAsync(Entity entity, string propName, CancellationToken cancellationToken = default(CancellationToken))
{
    return !await _dbContext.Entities
        .AnyAsync(x => x.PropName == propName && x.Id != entity.Id)
        .ContinueWith(x => !x.Result);
}

最后,我注意到您没有在代码中使用该CancellationToken。您应该将其传递给AnyAsync()(如果选择沿该路线,也应传递给ContinueWith())。