我正在修改现有项目以利用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)
,它就能正常运行。
我很好奇我是否正确地解决了这个问题,或者在处理异步时传递谓词有更好的选择。
答案 0 :(得分:5)
我认为ToListAsync
是IQueryable<T>
上的扩展方法,而不是IEnumerable<T>
。您应该将predicate
参数的类型更改为Expression<Func<Type, bool>>
。
由于IQueryable<T>
实施IEnumerable<T>
所有IEnumerable<T>
扩展方法,例如Where(this IEnumerable<T>, Func<T, bool>)
可用,但通常不是您打算使用的。
由于predicate
是Func<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();
}
干杯