Проблема с сохранением порядка FrozenSet в асинхронном методе получения данных с использованием .NET 8

В настоящее время я столкнулся с проблемой FrozenSet на C# с веб-API .NET 8, из-за которой он неожиданно управляет порядком данных. Ниже приведен метод, в котором я сталкиваюсь с таким поведением:

private async Task<FrozenSet<DemoDataRes>> GetDataAsync(int Id, string cacheKey, CancellationToken cancellationToken)
{
    var results = _cacheProvider.Get<FrozenSet<DemoDataRes>>(cacheKey, CacheKeys.DEMOCACHEGROUP);
    if (results is null)
    {
        results = (await (from avt in _DemoDbContext.Catalogs
                          where avt.Id == Id
                          orderby avt.Id
                          select new DemoDataRes
                          {
                              Id = avt.Id,
                              Type = avt.Name,
                          }
                         ).ToListAsync(cancellationToken));
        var value = results.ToFrozenSet();
        _cacheProvider.Set(cacheKey, value, CacheKeys.DEMOCACHEGROUP, Defaults.CacheExpiryMinutes);
    }
    return results;
}

Предполагается, что метод асинхронно извлекает данные из контекста базы данных, сопоставляет их с объектом DemoDataRes и сохраняет в кеше. Если кеш пуст, он извлекает данные из базы данных, упорядочивает их по идентификатору, а затем преобразует этот список в FrozenSet перед его кэшированием.

Проблема: я ожидаю, что FrozenSet будет управлять или сохранять порядок элементов, извлекаемых из базы данных с идентификатором orderby. Однако FrozenSet, похоже, не сохраняет порядок вставки, что не является предполагаемым поведением для наборов в целом.

Является ли это ожидаемым поведением FrozenSet при определенных обстоятельствах или на него может повлиять способ вставки или получения данных? Существуют ли какие-либо известные проблемы или соображения, связанные с FrozenSet в C#, которые могут привести к такому поведению? Каковы наилучшие методы обеспечения того, чтобы коллекция не управляла и не сохраняла порядок при кэшировании объектов данных?

Я сделал еще один образец POC со следующим кодом и обнаружил, что порядок сохраняется. Не знаю, почему код, возвращающий данные из базы данных, не поддерживает порядок при преобразовании их в FrozenSet.

Рабочий пример:

public async Task<FrozenSet<DemoDataRes>> GetDataAsync(CancellationToken cancellationToken)
{
     List<DemoDataRes> lstitem = new List<DemoDataRes>();
     DemoDataRes item1 = new DemoDataRes();
     item1.Type = "one";
     item1.CatalogId = 100;
     lstitem.Add(item1);
 
     DemoDataRes item2 = new DemoDataRes();
     item2.Type = "two";
     item2.CatalogId = 21;
     lstitem.Add(item2);
 
     DemoDataRes item3 = new DemoDataRes();
     item3.Type = "three";
     item3.CatalogId = 34;
     lstitem.Add(item3);
 
     DemoDataRes item4 = new DemoDataRes();
     item4.Type = "four";
     item4.CatalogId = 49;
     lstitem.Add(item4);
     lstitem = await Task.FromResult(lstitem.OrderByDescending(x => x.CatalogId).ToList());
     FrozenSet<FlexInspReportControlDataRes> frozenSet = lstitem.ToFrozenSet();
     return frozenSet;
}

Может ли кто-нибудь помочь мне здесь, предоставив свои рекомендации? Любая помощь будет принята с благодарностью.

Что такое DemoDataRes? Можете ли вы добавить минимально воспроизводимый пример ?

Guru Stron 10.07.2024 23:51

Спасибо @GuruStron за ваш ответ. Теперь я обновил вопрос рабочим примером. Рабочий образец работает без проблем. Я не понимаю, почему в этом случае порядок сохраняется при получении данных из базы данных.

santosh kumar patro 11.07.2024 12:41

1) добавьте определение для DemoDataRes 2) "Рабочий образец работает без проблем" - вы имеете в виду, что в данном случае порядок не поддерживается? 3) Всегда ли сохраняется «порядок из БД»? какие точные данные у вас есть в этом случае?

Guru Stron 11.07.2024 14:46

@GuruStron: DemoDataRes имеет два свойства, аналогичные рабочему примеру. При попытке использовать FrozenSet для данных, извлеченных из базы данных, порядок не сохраняется. Это работает с примером в памяти.

santosh kumar patro 11.07.2024 15:03

1) пожалуйста, добавьте в вопрос определение DemoDataRes. 2) «При попытке использовать FrozenSet для данных, извлеченных из базы данных, порядок не поддерживается» - это вполне ожидаемо, я не понимаю, в чем проблема.

Guru Stron 11.07.2024 16:04

Также второе утверждение противоречит вопросу: «Я ожидаю, что FrozenSet не будет управлять порядком элементов и не сохранять его, поскольку обычно это набор, в котором не должно быть никакого порядка. Однако FrozenSet, похоже, сохраняет порядок вставки, что это не предполагаемое поведение для наборов в целом».

Guru Stron 11.07.2024 16:06

И наконец — нет проблем, если он сохранит первоначальный порядок, нет никакой гарантии, что он не будет его поддерживать в некоторых случаях.

Guru Stron 11.07.2024 16:08

Извиняюсь @GuruStron за опечатку в вопросе и спасибо, что заметили ее. Моя проблема в том, что я вижу, что порядок данных, извлекаемых из базы данных, в этом случае не сохраняет порядок. Я попробовал еще один образец с данными в памяти и обнаружил, что все работает нормально. Следовательно, не уверен, в чем проблема, если данные получены из базы данных здесь. Любая помощь по этому запросу очень ценится.

santosh kumar patro 11.07.2024 19:49
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
8
57
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
Я ожидаю, что FrozenSet будет управлять или сохранять порядок элементов, извлекаемых из базы данных с идентификатором orderby.

FrozenSet предназначен не для этого. Это это:

оптимизирован для ситуаций, когда набор создается нечасто, но часто используется во время выполнения. Его создание требует относительно высоких затрат, но обеспечивает превосходную производительность поиска.

Как и многие другие коллекции, разработанные для обеспечения производительности поиска, они не дают никаких гарантий сохранения порядка элементов. Например, из дополнительных примечаний к API : документ HashSet (выделено мной):

Класс HashSet<T> обеспечивает высокопроизводительные операции над множествами. Набор — это коллекция, которая не содержит повторяющихся элементов и элементы которой не расположены в определенном порядке.

Если порядок или дублирование элементов для вашего приложения важнее производительности, рассмотрите возможность использования класса List<T> вместе с методом Sort.

и на самом деле внутренне ToFrozenSet будет конструировать HashSet<T> из входящих данных, поэтому сохранение порядка не гарантируется.

Как говорится в документации: если порядок важен, используйте List<>.

Другими вариантами могут быть:

  1. Кэшируйте две коллекции (упорядоченную + набор)
  2. Используйте что-то вроде SortedSet<T> , но обратите внимание, что такие методы, как Содержит, O(log n)
  3. Используйте словарь с индексом упорядоченного элемента как значение/часть значения.

Спасибо @GuruStron за подробный ответ :).

santosh kumar patro 12.07.2024 11:28

Другие вопросы по теме