根据这些帖子:
我应该能够使用Linq查询IReliableDictionary,但看起来该接口不再实现IEnumerable,并且Linq扩展不可用。至少在Microsoft.ServiceFabric.Data.Interfaces程序集的5.0.0.0版本中。
如果是这样,那么搜索IReliableDictionary的最佳方法是什么?
根据这些帖子:
我应该能够使用Linq查询IReliableDictionary,但看起来该接口不再实现IEnumerable,并且Linq扩展不可用。至少在Microsoft.ServiceFabric.Data.Interfaces程序集的5.0.0.0版本中。
如果是这样,那么搜索IReliableDictionary的最佳方法是什么?
using (ITransaction tx = this.StateManager.CreateTransaction())
{
var x = from item in (await clusterDictionary.CreateEnumerableAsync(tx)).ToEnumerable()
where item.Value.Status == ClusterStatus.Ready
orderby item.Value.CreatedOn descending
select new ClusterView(
item.Key,
item.Value.AppCount,
item.Value.ServiceCount,
item.Value.Users.Count(),
this.config.MaximumUsersPerCluster,
this.config.MaximumClusterUptime - (DateTimeOffset.UtcNow - item.Value.CreatedOn.ToUniversalTime()));
}
我不知道这是否是“最佳”方法,但我一直在使用以下方法:
public static async Task<IList<KeyValuePair<Guid, T>>> QueryReliableDictionary<T>(IReliableStateManager stateManager, string collectionName, Func<T, bool> filter)
{
var result = new List<KeyValuePair<Guid, T>>();
IReliableDictionary<Guid, T> reliableDictionary =
await stateManager.GetOrAddAsync<IReliableDictionary<Guid, T>>(collectionName);
using (ITransaction tx = stateManager.CreateTransaction())
{
IAsyncEnumerable<KeyValuePair<Guid, T>> asyncEnumerable = await reliableDictionary.CreateEnumerableAsync(tx);
using (IAsyncEnumerator<KeyValuePair<Guid, T>> asyncEnumerator = asyncEnumerable.GetAsyncEnumerator())
{
while (await asyncEnumerator.MoveNextAsync(CancellationToken.None))
{
if (filter(asyncEnumerator.Current.Value))
result.Add(asyncEnumerator.Current);
}
}
}
return result;
}
var queryResult = await QueryReliableDictionary<string>(this.StateManager, "CustomerCollection", name => !string.IsNullOrWhiteSpace(name) && (name.IndexOf("fred", StringComparison.OrdinalIgnoreCase) >= 0));
IAsyncEnumerable
是 dotnet 库的一部分,并且 C# 8.0 添加了语法糖来支持它。IAsyncEnumerable
,因此您无法将 dotnet 扩展方法和 C# 辅助程序应用于它。IAsyncEnumerable
转换为本机的 IAsyncEnumerable
。using System.Threading;
using System.Threading.Tasks;
using Generic = System.Collections.Generic;
using Fabric = Microsoft.ServiceFabric.Data;
public static class FabricAsyncEnumerableExtensions
{
/// <summary>
/// Converts ServiceFabric <see cref="Microsoft.ServiceFabric.Data.IAsyncEnumerable"/> to dotnet native <see cref="System.Collections.Generic.IAsyncEnumerable"/>.
/// </summary>
public static Generic.IAsyncEnumerable<T> ToGeneric<T>(this Fabric.IAsyncEnumerable<T> source) =>
new AsyncEnumerableWrapper<T>(source);
private class AsyncEnumerableWrapper<T> : Generic.IAsyncEnumerable<T>
{
private readonly Fabric.IAsyncEnumerable<T> _source;
public AsyncEnumerableWrapper(Fabric.IAsyncEnumerable<T> source) => _source = source;
public Generic.IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken _ = default)
{
Fabric.IAsyncEnumerator<T> enumerator = _source.GetAsyncEnumerator();
return new AsyncEnumeratorWrapper<T>(enumerator);
}
}
private class AsyncEnumeratorWrapper<T> : Generic.IAsyncEnumerator<T>
{
private readonly Fabric.IAsyncEnumerator<T> _source;
public AsyncEnumeratorWrapper(Fabric.IAsyncEnumerator<T> source) => _source = source;
public async ValueTask DisposeAsync() =>
await Task.Run(_source.Dispose).ConfigureAwait(false);
public async ValueTask<bool> MoveNextAsync() =>
await _source.MoveNextAsync(default).ConfigureAwait(false);
public T Current => _source.Current;
}
}
使用它就像调用扩展方法一样简单,然后将其用作常规的IAsyncEnumerable
:
Fabric.IAsyncEnumerable<KeyValuePair<Guid, Product>> asyncProducts = GetAsyncProducts();
return await asyncProducts.ToGeneric()
.Select(p => p.Value)
.ToListAsync()
.ConfigureAwait(false);
SelectAsync
、SelectManyAsync
和WhereAsync
。 - Eli Arbel