在IReliableDictionary上进行Linq查询

4

我已经进行了大量的搜索和代码调试,但是我没有找到一种对IReliableDictionary执行Linq查询的方法。我知道它与标准的IDictionary不同,但我很好奇是否有人尝试过。我开始觉得遗憾的是这似乎不可能。


3
可能是如何在IReliableDictionary中进行最佳搜索?的重复问题。 - Eli Arbel
5个回答

3

目前,没有一种普通的方法来在可靠字典上执行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查询操作。我已经写了一些代码,但需要进一步完善。我有一种预感,服务布局团队可能已经在处理这个问题,但如果或者何时发生这种情况,您的猜测和我的一样好。


谢谢!我也有这个问题,这很有帮助! :) - superaarthi

1

看起来微软在最新的 SF 发布中删除了使用 Linq 查询的功能。


请阅读此答案:https://dev59.com/Y5bfa4cB1Zd3GeqPuXxr - Eli Arbel

0

0

如果您需要处理比简单的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);
    }
}

这可能完全不适合您的情况,但似乎这是执行任何类型的“高级查询”的唯一方法。


CreateEnumerableAsync也不起作用。我已经尝试过了。它返回的是IAsyncEnumerator,而不是IEnumerable。 - g.t.w.d
是的,你的编辑就是我正在做的。但这并没有真正解决我的问题。我认为我需要以不同的方式来解决它。谢谢。 - g.t.w.d
没错。我添加了一个在Reliable Collections文档的评论中遇到的片段,详细说明了如何处理这个问题。 - Rion Williams
很抱歉它不能更有帮助。希望你能想出一种解决方法。 - Rion Williams
NP。感谢您尝试翻译。 - g.t.w.d

0

正确的LINQ无法与IAsyncEnumerator一起使用

var wgEnumerable = await voteDictionary.CreateEnumerableAsync(tx);
using(IAsyncEnumerator<KeyValuePair<string, int>> enumerator = wgEnumerable.GetAsyncEnumerator())
{
while(await enumerator.MoveNextAsync(CancellationToken.None))
{
//Do something
}
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接