В настоящее время я столкнулся с проблемой 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;
}
Может ли кто-нибудь помочь мне здесь, предоставив свои рекомендации? Любая помощь будет принята с благодарностью.
Спасибо @GuruStron за ваш ответ. Теперь я обновил вопрос рабочим примером. Рабочий образец работает без проблем. Я не понимаю, почему в этом случае порядок сохраняется при получении данных из базы данных.
1) добавьте определение для DemoDataRes
2) "Рабочий образец работает без проблем" - вы имеете в виду, что в данном случае порядок не поддерживается? 3) Всегда ли сохраняется «порядок из БД»? какие точные данные у вас есть в этом случае?
@GuruStron: DemoDataRes имеет два свойства, аналогичные рабочему примеру. При попытке использовать FrozenSet для данных, извлеченных из базы данных, порядок не сохраняется. Это работает с примером в памяти.
1) пожалуйста, добавьте в вопрос определение DemoDataRes
. 2) «При попытке использовать FrozenSet для данных, извлеченных из базы данных, порядок не поддерживается» - это вполне ожидаемо, я не понимаю, в чем проблема.
Также второе утверждение противоречит вопросу: «Я ожидаю, что FrozenSet не будет управлять порядком элементов и не сохранять его, поскольку обычно это набор, в котором не должно быть никакого порядка. Однако FrozenSet, похоже, сохраняет порядок вставки, что это не предполагаемое поведение для наборов в целом».
И наконец — нет проблем, если он сохранит первоначальный порядок, нет никакой гарантии, что он не будет его поддерживать в некоторых случаях.
Извиняюсь @GuruStron за опечатку в вопросе и спасибо, что заметили ее. Моя проблема в том, что я вижу, что порядок данных, извлекаемых из базы данных, в этом случае не сохраняет порядок. Я попробовал еще один образец с данными в памяти и обнаружил, что все работает нормально. Следовательно, не уверен, в чем проблема, если данные получены из базы данных здесь. Любая помощь по этому запросу очень ценится.
FrozenSet
предназначен не для этого. Это это:
оптимизирован для ситуаций, когда набор создается нечасто, но часто используется во время выполнения. Его создание требует относительно высоких затрат, но обеспечивает превосходную производительность поиска.
Как и многие другие коллекции, разработанные для обеспечения производительности поиска, они не дают никаких гарантий сохранения порядка элементов. Например, из дополнительных примечаний к API : документ HashSet (выделено мной):
Класс
HashSet<T>
обеспечивает высокопроизводительные операции над множествами. Набор — это коллекция, которая не содержит повторяющихся элементов и элементы которой не расположены в определенном порядке.
Если порядок или дублирование элементов для вашего приложения важнее производительности, рассмотрите возможность использования класса
List<T>
вместе с методомSort
.
и на самом деле внутренне ToFrozenSet будет конструировать HashSet<T>
из входящих данных, поэтому сохранение порядка не гарантируется.
Как говорится в документации: если порядок важен, используйте List<>
.
Другими вариантами могут быть:
O(log n)
Спасибо @GuruStron за подробный ответ :).
Что такое
DemoDataRes
? Можете ли вы добавить минимально воспроизводимый пример ?