#azure-service-fabric
#azure-service-fabric
Вопрос:
Я пытаюсь реализовать разбивку на страницы на основе курсора для надежного словаря. Я знаю, что IReliableDictionary
ключи должны быть реализованы IComparable
, и что IReliableDictionary
этот метод для перечисления словарных записей:
IAsyncEnumerable<KeyValuePair<TKey,TValue>>>
CreateEnumerableAsync (
ITransaction txn,
Func<TKey,bool> filter,
EnumerationMode enumerationMode);
Когда EnumerationMode.Ordered
используется, я предполагаю, что мы перечисляем пары ключ-значение в соответствии с IComparable
реализацией ключа.
Можем ли мы также предположить, что filter
параметр применяется к каждому ключу в порядке IComparable
реализации ключа? Может быть, другой способ спросить — расположены ли ключи в памяти и / или перечислены в порядке их IComparable
реализации? Если да, задокументировано ли это поведение или его следует рассматривать как деталь реализации, которая может измениться?
Ответ №1:
Я провел эксперимент, используя образец веб-сайта для голосования, и ключи, похоже, фильтруются в порядке их IComparable
реализации, с некоторыми оговорками:
- Похоже, что фильтр может запускаться несколько раз по одному и тому же ключу
- Фильтр может быть применен к элементам, которые были недавно удалены
VotingData.Controllers.VoteDataController
имеет следующие операции get и put для составления списка и добавления категорий голосования:
[HttpPut("{name}")]
public async Task<IActionResult> Put(string name)
{
IReliableDictionary<string, int> votesDictionary = await this.stateManager.GetOrAddAsync<IReliableDictionary<string, int>>("counts");
using (ITransaction tx = this.stateManager.CreateTransaction())
{
await votesDictionary.AddOrUpdateAsync(tx, name, 1, (key, oldvalue) => oldvalue 1);
await tx.CommitAsync();
}
return new OkResult();
}
Я изменил, Get
чтобы перечислять votesDictionary
по порядку, и применил фильтр, который формирует список ключей, видимых фильтром:
[HttpGet]
public async Task<IActionResult> Get()
{
CancellationToken ct = new CancellationToken();
IReliableDictionary<string, int> votesDictionary = await this.stateManager.GetOrAddAsync<IReliableDictionary<string, int>>("counts");
var filteredKeys = new List<string>();
using (ITransaction tx = this.stateManager.CreateTransaction())
{
IAsyncEnumerable<KeyValuePair<string, int>> list = await votesDictionary.CreateEnumerableAsync(tx, key =>
{
lock (this.locker)
{
filteredKeys.Add(key);
return true;
}
},
EnumerationMode.Ordered);
IAsyncEnumerator<KeyValuePair<string, int>> enumerator = list.GetAsyncEnumerator();
List<KeyValuePair<string, int>> result = new List<KeyValuePair<string, int>>();
while (await enumerator.MoveNextAsync(ct))
{
result.Add(enumerator.Current);
}
return this.Json(result);
}
}
Я добавил ключи в словарь в случайном алфавитном порядке и обновил страницу для выполнения Get
запроса. При каждом обновлении filteredKeys
коллекция содержала мои записи в отсортированном алфавитном порядке. Как упоминалось выше, коллекция иногда содержала повторяющиеся записи для определенных строк. Когда я удалил элементы из коллекции и обновил страницу, я обнаружил, что удаленные ключи все еще были добавлены в filteredKeys
, хотя эти элементы не были возвращены в результирующем перечислении.
Комментарии:
1. Не в восторге от принятия моего собственного ответа в этом случае — хотелось бы увидеть что-то более авторитетное. Тем не менее, эксперимент показывает, что, хотя фильтры применяются в порядке следования ключей, на них нельзя положиться для точного перечисления текущего набора ключей (никаких удаленных ключей, каждый ключ обрабатывается один раз).