我已经进行了大量的搜索和代码调试,但是我没有找到一种对IReliableDictionary
执行Linq查询的方法。我知道它与标准的IDictionary
不同,但我很好奇是否有人尝试过。我开始觉得遗憾的是这似乎不可能。
我已经进行了大量的搜索和代码调试,但是我没有找到一种对IReliableDictionary
执行Linq查询的方法。我知道它与标准的IDictionary
不同,但我很好奇是否有人尝试过。我开始觉得遗憾的是这似乎不可能。
目前,没有一种普通的方法来在可靠字典上执行linq查询。尽管如此,你可以做几件事情。正如先前所述,CreateEnumerableAsync方法存在的原因是因为Service Fabric将可靠字典写入磁盘,但如果您知道底层集合很小并且可以承受性能损失,则以下类将起作用。
public static class AsyncEnumerableExtensions
{
/// <summary>
/// Converts the collection to a list
/// </summary>
/// <typeparam name="TValType">value type of the collection</typeparam>
/// <param name="enumerator">enumerator to convert</param>
/// <param name="ct">cancellation token for the async operations</param>
/// <param name="tx">tx to enforce that this is called in a transactional context</param>
/// <returns>a list containing all elements in the origin collection</returns>
public static async Task<IList<TValType>> ToListAsync<TValType>(
this IAsyncEnumerator<TValType> enumerator,CancellationToken ct, ITransaction tx)
{
IList<TValType> ret = new List<TValType>();
while (await enumerator.MoveNextAsync(ct).ConfigureAwait(false))
{
ret.Add(enumerator.Current);
}
return ret;
}
/// <summary>
/// Converts the collection to a list
/// </summary>
/// <typeparam name="TValType">value type of the collection</typeparam>
/// <param name="enumerator">enumerator to convert</param>
/// <param name="tx">tx to enforce that this is called in a transactional context</param>
/// <returns>a list containing all elements in the origin collection</returns>
public static Task<IList<TValType>> ToListAsync<TValType>(
this IAsyncEnumerator<TValType> enumerator, ITransaction tx)
{
return enumerator.ToListAsync(CancellationToken.None,tx);
}
/// <summary>
/// Converts the collection to a list
/// </summary>
/// <typeparam name="TValType">value type of the collection</typeparam>
/// <param name="enumerable">enumerator to convert</param>
/// <param name="ct">cancellation token for the async operations</param>
/// <param name="tx">tx to enforce that this is called in a transactional context</param>
/// <returns>a list containing all elements in the origin collection</returns>
public static Task<IList<TValType>> ToListAsync<TValType>(this IAsyncEnumerable<TValType> enumerable,
CancellationToken ct, ITransaction tx)
{
return enumerable.GetAsyncEnumerator().ToListAsync(ct,tx);
}
/// <summary>
/// Converts the collection to a list
/// </summary>
/// <typeparam name="TValType">value type of the collection</typeparam>
/// <param name="enumerable">enumerator to convert</param>
/// <param name="tx">tx to enforce that this is called in a transactional context</param>
/// <returns>a list containing all elements in the origin collection</returns>
public static Task<IList<TValType>> ToListAsync<TValType>(this IAsyncEnumerable<TValType> enumerable, ITransaction tx)
{
return enumerable.GetAsyncEnumerator().ToListAsync(tx);
}
}
您也可以实现自己的自定义枚举器和扩展方法,以高效地执行与您的数据类似的linq查询操作。我已经写了一些代码,但需要进一步完善。我有一种预感,服务布局团队可能已经在处理这个问题,但如果或者何时发生这种情况,您的猜测和我的一样好。
看起来微软在最新的 SF 发布中删除了使用 Linq 查询的功能。
在将ServiceFabric的IAsyncEnumerable
转换为dotnet之后,可以使用异步Linq。
请参考此答案: 将IReliableDictionary转换为IList
如果您需要处理比简单的GetByKey()
更复杂的操作,您需要通过IReliableDictionary.CreateEnumerable()
方法显式地创建一个本地集合,然后您就可以像以下示例一样查询它,该示例来自于此讨论中的评论:
IAsyncEnumerable<KeyValuePair<int, string="">> enumerable = await myDictionary.CreateEnumerableAsync(tx);
using (IAsyncEnumerator<KeyValuePair<int, string="">> e = enumerable.GetAsyncEnumerator())
{
while (await e.MoveNextAsync(cancellationToken).ConfigureAwait(false))
{
doSomething(e.Current);
}
}
这可能完全不适合您的情况,但似乎这是执行任何类型的“高级查询”的唯一方法。
正确的LINQ无法与IAsyncEnumerator一起使用
var wgEnumerable = await voteDictionary.CreateEnumerableAsync(tx);
using(IAsyncEnumerator<KeyValuePair<string, int>> enumerator = wgEnumerable.GetAsyncEnumerator())
{
while(await enumerator.MoveNextAsync(CancellationToken.None))
{
//Do something
}
}