使用异步和等待模式一步高效地将 IQueryable<TSource> 转换为 ImmutableArray<TSource>

Spa*_*man 6 .net c# entity-framework entity-framework-core

我正在尝试以最有效的方式将集合选择不可变数组中。

我还想明确结果集的意图:只读/不可变/不跟踪

var someCollection = await _dataContext
    .Set<someType>()
    .AsNoTracking()
    .ToArrayAsync();
Run Code Online (Sandbox Code Playgroud)

我可以这样做,然后转换为不可变,但这看起来很疯狂。

var someImmutableCollection = someCollection
    .ToImmutableArray();
Run Code Online (Sandbox Code Playgroud)

我也可以这样做:

var someCollection = _dataContext
    .Set<someType>()
    .AsNoTracking()
    .ToImmutableArray();
Run Code Online (Sandbox Code Playgroud)

但这不是async

有没有理由ToImmutableArrayAsync()吗?

或者是否有更好的方法async从 efcore 获取不可变数组?

AAA*_*ddd 7

我可以这样做,然后转换为不可变,但这看起来很疯狂。

var someImmutableCollection = someCollection
    .ToImmutableArray();
Run Code Online (Sandbox Code Playgroud)

疯狂的?没那么多。我们看一下源码

public static async Task<TSource[]> ToArrayAsync<TSource>(
     [NotNull] this IQueryable<TSource> source,
     CancellationToken cancellationToken = default)
       => (await source.ToListAsync(cancellationToken).ConfigureAwait(false))
           .ToArray(); // anti-climax
Run Code Online (Sandbox Code Playgroud)

嗯,那里并没有发生太多魔法。

只需创建您自己的扩展

public class MySuperExtensions
{   
    public static async Task<ImmutableArray<TSource>> ToImmutableArrayAsync<TSource>(
         [NotNull] this IQueryable<TSource> source,
         CancellationToken cancellationToken = default)
           => (await source.ToListAsync(cancellationToken).ConfigureAwait(false))
               .ToImmutableArray(); // yehaa
}
Run Code Online (Sandbox Code Playgroud)

危机解除,问题解决。


或者更有效地节省额外的分配和IAsyncStateMachine实施

public static async Task<ImmutableArray<TSource>> ToImmutableArrayAsync<TSource>(
   [NotNull] this IQueryable<TSource> source,
   CancellationToken cancellationToken = default)
{
   var builder = ImmutableArray.CreateBuilder<TSource>();
   await foreach (var element in source.AsAsyncEnumerable().WithCancellation(cancellationToken))
       builder.Add(element);

   return builder.ToImmutable();
}
Run Code Online (Sandbox Code Playgroud)