我正在尝试遍历结果集,运行查询以检索数据,然后将该数据添加到列表并返回它。
问题是,我试图异步执行此操作,我收到错误:
'System.Collections.Generic.List' 不包含'ToListAsync'的定义和最佳扩展名 方法过载 'System.Data.Entity.QueryableExtensions.ToListAsync(System.Linq.IQueryable)' 有一些无效的论点
以下是该方法的代码:
public async Task<List<IHFData>> GetHFServiceData(string wtTransfereeId)
{
var hfDataList = new List<HFData>();
Parallel.ForEach(aauthorizationList, item =>
{
// code to retrieve data from database (truncated)
HFData hfData = Db.hfAuthorizations.AsNoTracking()....SingleOrDefault();
hfDataList.Add(hfData);
}
return await hfDataList.ToListAsync(); // errors on this line
}
如何异步构建和返回我的列表?
答案 0 :(得分:5)
正如错误消息告诉您的那样,没有List
方法可以异步创建列表。无论如何,你已经有了一个清单。
从多个线程添加项目到列表也是不安全的,正如您从并行foreach循环中所做的那样。
您也不应该首先对集合中的每个项目执行数据库查询。相反,您应该执行单个数据库查询,该查询根据您拥有的列表中的信息获取所需的所有项目。该查询应以对ToListAsync
的调用结束。
此处也不需要async
方法,您只需直接返回ToListAsync
的结果。
答案 1 :(得分:3)
您的代码存在一些巨大问题。
首先,您在hfDataList.Add
内部调用Parallel.ForEach
,List<T>
不是线程安全的,您无法在不锁定的情况下调用Add。
第二,因为错误告诉您ToListAsync
只能在具有接口IQueryable<T>
的类型上调用,所以您在List<T>
上调用它而不实现该接口。
执行查询的正确方法是
public Task<List<IHFData>> GetHFServiceData(string wtTransfereeId)
{
return Db.hfAuthorizations.AsNoTracking()....ToListAsync()
}
你需要修改你所取出的....
中的任何内容,以便一次返回一组结果而不是一个结果。
此外await
是不必要的,它是您函数中的最后一行,您只需返回Task directly
并简化生成的代码并减少开销。
如果您无法将其更改为设置查询(并且您应该尝试,它将极大地提高您的性能)那么以旧方式执行此操作的方法是删除并行(实体框架可以&# 39; t处理它或者只做一个正常的foreach循环,然后等待异步版本的SingleOrDefault
public async Task<List<IHFData>> GetHFServiceData(string wtTransfereeId)
{
var hfDataList = new List<HFData>();
foreach(var item in aauthorizationList)
{
// code to retrieve data from database (truncated)
HFData hfData = await Db.hfAuthorizations.AsNoTracking()....SingleOrDefaultAsync(); //This method is now async.
hfDataList.Add(hfData);
}
//just return the list when you are done.
return hfDataList;
}