FreeSql
FreeSql copied to clipboard
添加ToAsyncEnumerable返回异步流功能
Feature 特性
public class FreeSqlAsyncEnumerable<T>(DbDataReader reader) : IAsyncEnumerable<T>
{
public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken())
{
return new FreeSqlAsyncEnumerator<T>(reader, cancellationToken);
}
}
public class FreeSqlAsyncEnumerator<T>(DbDataReader reader, CancellationToken cancellationToken) : IAsyncEnumerator<T>
{
public T Current => (T) Utils.ExecuteArrayRowReadClassOrTuple(flag, typeof(T), indexes, reader, 0, _util).Value;
public ValueTask<bool> MoveNextAsync()
{
return new ValueTask<bool>(reader.ReadAsync(cancellationToken));
}
public async ValueTask DisposeAsync()
{
await reader.CloseAsync();
await reader.DisposeAsync();
}
}
简要描述原因
针对大数据导出和后续处理非常有用。ToChunk和ToChunkAsync只支持传递委托进去,使得代码耦合。而且没有数据返回。 返回IAsyncEnumberable接口,可以把查询和后续数据处理分离出来,代码不耦合。而且还可以返回数据。其次避免ToListAsync中List扩容的数据复制带来的开销。
使用场景
freeSql.Select<T>.ToAsyncEnumerable(cancellationToken);
freeSql.Select<T>.ToAsyncEnumerable(t => new T2()
{
Id = t.Id
}, cancellationToken);
freeSql.Select<T1, T2>.ToAsyncEnumerable((t1, t2) => new T3()
{
Id = t1.Id,
Name = t2.Name
}, cancellationToken);
之前是考虑到使用者,返回的对象不一定 Disponse,然后把锅甩到 orm 身上。
之前是考虑到使用者,返回的对象不一定 Disponse,然后把锅甩到 orm 身上。
可以改造一下MoveNextAsync方法。当返回false的时候立马Dispose掉。这样的话在流读取完后就立即释放掉。
因为EfCore本来就有提供这个接口方法,所以我希望FreeSql也能实现。
public class FreeSqlAsyncEnumerator<T>(DbDataReader reader, CancellationToken cancellationToken) : IAsyncEnumerator<T>
{
public T Current => (T) Utils.ExecuteArrayRowReadClassOrTuple(flag, typeof(T), indexes, reader, 0, _util).Value;
public async ValueTask<bool> MoveNextAsync()
{
var result = await reader.ReadAsync(cancellationToken);
if (!result) await DiposeAsync();
return result;
}
public async ValueTask DisposeAsync()
{
await reader.CloseAsync();
await reader.DisposeAsync();
}
}
@2881099 这功能可以实现吗
暂时没时间,上次尝试过一次,改动较大
大佬有空试下。
await foreach (var items in fsql.Select<User1>().ToChunkAsyncEnumerable(10))
{
foreach (var item in items)
Console.WriteLine(item.Nickname);
}