如何将IQueryable替换为异步操作?

时间:2018-08-13 13:18:37

标签: c# linq entity-framework-core

假设我在数据库中有一个具有多个关系的Projects表。我的C#代码的DB层中的各种不同查询都可能希望将此表与其他表连接起来。因此,我摘录了以下内容:

public IQueryable<Project> QueryProject(Project prj)
{
    return Context.Projects.Where(p => p.id == prj.id);
}

...因此我可以在其他各种情况下重用此方法,例如...

_queryService.QueryProject(prj).Include(p => p.Users)

...或

_queryService.QueryProject(prj).Include(p => p.Artefacts)

...等等。有一点,我认为使动作方法异步是一个好主意,所以我尝试以下方法:

await _queryService.QueryProject(prj).Include(p => p.Artefacts).SingleAsync();

但是,当我尝试使用QueryProject方法进行任何操作的时候,我从单元测试中得到以下错误:

  

源IQueryable没有实现IAsyncEnumerable。只有实现IAsyncEnumerable的源才能用于Entity Framework异步操作。

显然,我不应该将IQueryable用作我的第一个QueryProject抽象的返回类型。但是,我正在努力寻找可行的替代方案。我不希望在执行QueryProject期间对实体进行任何数据库检索。我也对仅隐藏此错误却没有给我带来任何好处的黑客不感兴趣。我只是想抽象掉重复的代码。

.NET core 2.1是否支持某种类型的替代方案?

P.S。 Ivan Stoev提出了一个有效的担忧,问题可能出在我的单元测试中。这是我的模拟代码供参考(使用Moq):

mockServices.Setup(x => x.QueryProject(It.IsAny<SomeProjectAbstraction>()))
    .Returns(new List<Project>
    {
        new Project
        {
            Name = ...
        }
    }.AsQueryable());

1 个答案:

答案 0 :(得分:1)

IQueryable<T>是一种结构,使您可以在数据库处理查询之前 建立查询。这没有什么不同步的。异步涉及的部分是当您实际将查询发送到数据库并等待响应时(使用SingleAsync()时会发生这种情况)。那时,您不再拥有IQueryable<T>,因为现在它是实际结果集。