转换 IQueryable 以实现 IAsyncEnumerable [重复]

Posted

技术标签:

【中文标题】转换 IQueryable 以实现 IAsyncEnumerable [重复]【英文标题】:Converting IQueryable to implement IAsyncEnumerable [duplicate] 【发布时间】:2017-04-07 09:30:27 【问题描述】:

我在方法中有一个查询:

private readonly IEntityReader<Customer> _reader;

public async Task<IEnumerable<Customer>> HandleAsync(GetCustomer query)

    var result = _reader.Query()
        .Include(customer => customer.Organization)
        .Where(customer => customer.Name == query.Name);

    return await result.ToListAsync();

哪个有这个单元测试:

[Fact]
public async Task HandleGetCustomer_ReturnsCustomer_WhenNameMatches()

    // Arrange
    var customers = new List<Customer>()
    
        new Customer
        
            Id = new Guid("d4e749ba-6874-40f4-9134-6c9cc1bc95fe"),
            Name = "John Doe",
            Age = 18,
            Organization = new Organization
            
                Id = new Guid("b2ba06c9-5c00-4634-b6f7-80167ea8c3f1"),
                Name = "TheCompany",
                Number = 42
            
        ,
        new Customer
        
            Id = new Guid("0679ceb5-3d4f-41f3-a1b0-b167e1ac6d7e"),
            Name = "Another Guy",
            Age = 39,
            Organization = new Organization
            
                Id = new Guid("b2ba06c9-5c00-4634-b6f7-80167ea8c3f1"),
                Name = "TheCompany",
                Number = 42
            
        
    .AsQueryable();

    var entityReader = new Mock<IEntityReader<Customer>>(MockBehavior.Strict);
    entityReader.Setup(reader => reader.Query()).Returns(customers);

    var query = new GetCustomer
    
        Name = "John Doe"
    ;

    var handler = new HandleGetCustomer(entityReader.Object);

    // Act
    var result = await handler.HandleAsync(query);

    // Assert
    Assert.NotNull(result);
    Assert.True(result.Count() == 1);
    Assert.True(result.FirstOrDefault().Id == new Guid("d4e749ba-6874-40f4-9134-6c9cc1bc95fe"));

显然对.ToListAsync(); 的调用失败是因为:

源 IQueryable 未实现 IAsyncEnumerable。只有来源 实现 IAsyncEnumerable 可用于实体框架 异步操作。

扩展方法是来自 Entity Framework Core 的方法。

如何将我的客户列表转换为IAsyncEnumerable

作为参考,IEntityReader接口定义如下:

public interface IEntityReader<out TEntity> where TEntity : Entity

    IQueryable<TEntity> Query();

【问题讨论】:

看看这里***.com/a/40500030/5233410 解决方案可以修改并应用于您的用例 似乎该代码正在DbSet&lt;T&gt; 上运行,但我会看看。 是的,它也是 IQueriable 类型。可以应用相同的策略。或者您可以查看 ef 源代码内部使用的 AsAsyncEnumerable 扩展方法。 不同之处在于他们直接在DbContext/DbSet&lt;T&gt; 上进行测试,我在其中模拟一个接口,该接口具有返回IQuerable&lt;T&gt; 的方法。 @Nkosi 你是对的,我想出了一个解决办法。 :-) 等一下,我会发布答案。 【参考方案1】:

感谢@Nkosi,这是解决方案:

How to mock an async repository with Entity Framework Core的代码sn-p随着客户列表的变化:

var customers = new TestAsyncEnumerable<Customer>(new List<Customer>

    new Customer
    
        Id = new Guid("d4e749ba-6874-40f4-9134-6c9cc1bc95fe"),
        Name = "John Doe",
        Age = 18,
        Organization = new Organization
        
            Id = new Guid("b2ba06c9-5c00-4634-b6f7-80167ea8c3f1"),
            Name = "TheCompany",
            Number = 42
        
    ,
    new Customer
    
        Id = new Guid("0679ceb5-3d4f-41f3-a1b0-b167e1ac6d7e"),
        Name = "Another Guy",
        Age = 39,
        Organization = new Organization
        
            Id = new Guid("b2ba06c9-5c00-4634-b6f7-80167ea8c3f1"),
            Name = "TheCompany",
            Number = 42
        
    
.AsQueryable();

【讨论】:

以上是关于转换 IQueryable 以实现 IAsyncEnumerable [重复]的主要内容,如果未能解决你的问题,请参考以下文章

IEnumerable 类型如何转换成IQueryable类型

将 IQueryable<int> 转换为 <int>

将 IQueryable<EntityObject> 转换为 IQueryable<Specific>

更改存储库以支持 IQueryable(LINQ to SQL 查询)

将 IQueryable 转换为简单对象

尝试返回 IQueryable<MyType> 时出现转换错误