将func <type,bool =“”>作为参数传递给异步方法</type,>时出错

时间:2013-03-25 23:08:37

标签: c# task-parallel-library entity-framework-6

我正在修改现有项目以利用EF6(alpha3)异步扩展方法。我有一个方法,它接受一个func参数,它被传递到linq到实体查询。以下是工作代码的示例,pre-async:

public IEnumerable<type> GetTypeSet(Func<Type, bool> predicate)
    {
        return dbSet.Where(d => d.isPublic == true).Where(predicate).tolist();
    }

应用异步后:

public async Task<IEnumerable<Type>> GetTypeSet(Func<Type, bool> predicate)
    {
        return await(dbSet.Where(d => d.isPublic == true)
        .Where(predicate)).ToListAsync();
    }

此时,我收到一条错误,指出IEnumerable没有ToListAsync的定义。如果我删除了.Where(predicate),它就能正常运行。

我很好奇我是否正确地解决了这个问题,或者在处理异步时传递谓词有更好的选择。

3 个答案:

答案 0 :(得分:5)

我认为ToListAsyncIQueryable<T>上的扩展方法,而不是IEnumerable<T>。您应该将predicate参数的类型更改为Expression<Func<Type, bool>>

由于IQueryable<T>实施IEnumerable<T>所有IEnumerable<T>扩展方法,例如Where(this IEnumerable<T>, Func<T, bool>)可用,但通常不是您打算使用的。

由于predicateFunc<Type, bool>的类型

dbSet.Where(d => d.isPublic == true)
如果您想要IEnumerable<Type>,则

IQueryable<Type>。 将predicate的类型更改为Expression<Func<Type, bool>>会导致使用Queryable.Where扩展方法,并根据需要返回IQueryable<Item>

答案 1 :(得分:5)

您的.Where( predicate )使用的是IEnumerable.Where扩展程序,而不是IQueryable.Where

这意味着,谓词正在您的应用程序中运行,而不是在数据库服务器上运行。

如果您想使用IQueryable.Where,则必须将谓词作为Expression<Func<type, bool>> - 表达式树传递 - 而不是作为委托。

因此,只需将方法签名更改为:

public async Task<IEnumerable<Type>>
  GetTypeSet(Expression<Func<Type, bool>> predicate)
{
  ...

答案 2 :(得分:3)

您必须使该函数采用Expression,否则Where扩展将在IEnumerable上回退,而不是IQueryable。 ToListAsync只是IQueryable上的扩展方法。

public async Task<IEnumerable<Type>> GetTypeSet(Expression<Func<Type, bool>> predicate)
{
    return await(dbSet.Where(d => d.isPublic == true)
    .Where(predicate)).ToListAsync();
}

干杯