如何将SelectMany转换为Async LINQ Call

时间:2018-04-04 02:39:23

标签: c# linq

如何将以下内容转换为Async Linq调用。我知道LINQ对Async调用没有最好的效果,SelectMany直接无效。我现在运气好了很多东西。谢谢。

我如何将其转换为ASYNC电话?

public class Foo
{
    public int Id { get; set; }
    public int? ParentId { get; set; }  
    // other props
}
You can get children of one item using:

List<Foo> GetChildren(List<Foo> foos, int id)
{
    return foos
        .Where(x => x.ParentId == id)
        .Union(foos.Where(x => x.ParentId == id)
            .SelectMany(y => GetChildren(foos, y.Id))
        ).ToList();
}
For ex.

List<Foo> foos = new List<Foo>();

foos.Add(new Foo { Id = 1 });
foos.Add(new Foo { Id = 2, ParentId = 1 });
foos.Add(new Foo { Id = 3, ParentId = 2 });
foos.Add(new Foo { Id = 4 });

GetChild(foos, 1).Dump(); // will give you 2 and 3 (ids)

1 个答案:

答案 0 :(得分:0)

  

LINQ使用async-await完美运行。我认为你的错误观念是   因为在实际执行查询时您不清楚。

您不会说明您是使用Iqueryable还是IEnumerable,但原则保持不变。

有两种LINQ语句:只会更改查询的语句和将执行查询的语句。

您可以看到linq语句属于哪个组(串联)。如果结果为IEnumerable<TResult>IQueryable<TResult>,则仅创建查询。它尚未执行。尚未访问数据库(或者在文件的情况下:未读取文件的内容)。

如果结果是List<TResult>,一个TResultBoolean等,那么不是IEnumerable,那么查询实际上就会执行。或者更确切地说:GetEnumeratorMoveNext已被调用,数据实际上被提取并放入结果中。

第一组的方法有WhereSelect,&#39; Union&#39; GroupJoin&#39;,GroupBy等。

第二组的方法是ToListToDictionary,还有FirstOrDefaultAny。调用这些函数时,实际访问数据库,或实际处理文件内容等。

更改查询的方法并不耗时。因此,使这些功能等待是没有用的。但是,查询等待数据库(等)是非常有用的。因此,您可以找到它们的异步版本。例如,您可以找到IQueryable.ToListAsyncIQueryable.ToDictionaryAsyncIQueryable.FirstOrDefaultAsync甚至IQueryable.AnyAsync

等方法

返回查询:

Task<List<Foo>> GetChildrenAsync(IEnumerable<Foo> foos, int id)
{
   var query = foos.Where(foo => foo.ParentId == id)
       .Union(foos
           .Where(foo => foo.ParentId == id)
           .SelectMany(foo => GetChildren(foos, y.Id));
   // until now only the query has been created.
   // collection foos has not been accessed yet.

   // execute the query:
   var result = await query.ToListAsync();
   return result;

}

如果按照这些较小的步骤划分语句,则可以更轻松地使用调试器查看实际调用GetEnumerator的时间。如果需要,您当然可以将其改为一个重要声明。

顺便说一句,如果您的输入真的是List?在这种情况下,我相当肯定,使你的功能等待是没有用的。 async-await仅在您的线程必须等待另一个线程或进程完成才能继续之前有用。但这超出了这个问题的范围。