Format persistence keys with the invariant culture [patch] - #63
Merged
Merged
Conversation
FileSystem and Temp built file names with key.ToString(), which uses the current culture, while GetAllKeysAsync parsed them back with the invariant culture. Under de-DE a double key 1.5 was stored as 1,5 and listed as 15, and data stored under one culture could not be found under another. Both providers now format keys through PersistenceProviderUtilities.FormatKey, which uses round-trip formats, and TryConvertToKey parses DateTime and DateTimeOffset keys with round-trip kind. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CzC1o7LFYHYaoWmVy1NLcp
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CzC1o7LFYHYaoWmVy1NLcp
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CzC1o7LFYHYaoWmVy1NLcp
|
This was referenced Sep 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Fixes #46
What changed
FileSystemPersistenceProviderandTempPersistenceProviderbuilt file names withkey.ToString(), which uses the current culture.GetAllKeysAsyncthen parsed those names back with the invariant culture. Under de-DE, that caused two problems:doublekey1.5was stored as1,5.jsonand listed back as15.DateTimekey came back with its day and month swapped.Data written under one culture also could not be found under another.
PersistenceProviderUtilities.FormatKey<TKey>. This is the one helper both providers now use to turn a key into its file-name text, so the two cannot drift apart:double/floatuse the round-trip"R"format.DateTime/DateTimeOffsetuse ISO 8601"O".IFormattabletypes format with the invariant culture.TryConvertToKeynow parsesDateTimewithDateTimeStyles.RoundtripKind, so a UTC key is not converted to local time on the way back. It also parsesDateTimeOffset, whichConvert.ChangeTypecannot convert at all.Compatibility note
Release note: files written before this change under a culture that differs from invariant keep their old names, and the new format will not find them. For example, a
1,5.jsonwritten under de-DE.DateTimekeys are also named differently now, in every culture. The old name was a culture-specific short date with seconds precision; the new one is the ISO 8601 round-trip form. String, integer and GUID keys are unaffected. Under invariant-like cultures,doublekeys are unaffected too, because .NET's defaultdouble.ToString()is already the shortest round-trippable form.The triage suggested a fallback lookup or a release note. I went with the note, because a fallback would have to cover
Exists,Retrieve,Removeand enumeration in both providers.Tests
In
PersistenceNamingTests:FileSystem_Double_And_Date_Keys_Round_Trip_Across_CulturesandTemp_Double_And_Date_Keys_Round_Trip_Across_Cultureseach:doubleandDateTimekeys under a comma-decimal, day-first cultureGetAllKeysAsyncreturns exactly those keysRetrieveAsyncstill finds each oneFormatKey_Ignores_The_Current_Culturepins the formatted text.The test cultures are cloned from the invariant culture rather than built with
new CultureInfo("de-DE"), so the tests also run on machines in globalization-invariant mode with no ICU data. This container is one of those.Verification
TryConvertToKeychanges reverted (keeping onlyFormatKeyso the tests compile), both round-trip tests fail: the expected key1,5is missing from the listed keys.Essentialsand both providers build for every target, including netstandard2.1, with 0 warnings.🤖 Generated with Claude Code
https://claude.ai/code/session_01CzC1o7LFYHYaoWmVy1NLcp
Generated by Claude Code