What is wrong
The code that turns a key into a file name and the code that turns a file name back into a key use different cultures.
- Writing:
FileSystemPersistenceProvider.GetFilePath (Essentials.PersistenceProviders.FileSystem/FileSystemPersistenceProvider.cs:233) and the same method in Essentials.PersistenceProviders.Temp/TempPersistenceProvider.cs:257 both call key.ToString(), which formats with the current culture:
string fileName = PersistenceProviderUtilities.GetSafeFileName(key.ToString()!) + _serializationProvider.FileExtension;
- Reading:
GetAllKeysAsync (FileSystem line 191, Temp line 188) calls PersistenceProviderUtilities.TryConvertToKey. For any type other than string, Guid and int, that uses Convert.ChangeType(value, typeof(TKey), CultureInfo.InvariantCulture) (Essentials/PersistenceProviderUtilities.cs:180), which parses with the invariant culture.
In a culture whose decimal separator or date order differs from invariant, a stored key is listed back as a different key. That key does not exist, so ExistsAsync and RetrieveAsync on it miss.
Second consequence: because the file name depends on the culture, data stored under one culture cannot be found when the process runs under another (1.5 is stored as 1,5.json under de-DE and looked up as 1.5.json under en-US).
Failure scenario
CultureInfo.CurrentCulture = new CultureInfo("de-DE");
var p = new FileSystemPersistenceProvider<double>(new NativeFileSystemProvider(), new JsonSerializationProvider(), dir);
await p.StoreAsync(1.5, "hello");
var keys = await p.GetAllKeysAsync();
Output:
files: 1,5.json
keys: 15
Exists(15)=False Retrieve=<null>
Expected: keys: 1.5, and retrieving that key returns "hello".
With DateTime keys, new DateTime(2026,3,4,5,6,7) is listed as 2026-04-03T05:06:07 (day and month swapped).
How it was verified
A scratch console app referencing the FileSystem persistence, Native filesystem and Json serialization projects, run against HEAD, produced the output above.
Suggested fix / acceptance criteria
- Format keys with the invariant culture when building file names (
IFormattable.ToString(null, CultureInfo.InvariantCulture) or Convert.ToString(key, CultureInfo.InvariantCulture)), using a round-trippable format ("R"/"O") where it matters. Share one helper between the FileSystem and Temp providers so they cannot drift.
- Add a test that sets
CurrentCulture to de-DE, stores double and DateTime keys, and asserts that GetAllKeysAsync returns exactly the stored keys and that RetrieveAsync finds them after CurrentCulture is switched to en-US.
What is wrong
The code that turns a key into a file name and the code that turns a file name back into a key use different cultures.
FileSystemPersistenceProvider.GetFilePath(Essentials.PersistenceProviders.FileSystem/FileSystemPersistenceProvider.cs:233) and the same method inEssentials.PersistenceProviders.Temp/TempPersistenceProvider.cs:257both callkey.ToString(), which formats with the current culture:GetAllKeysAsync(FileSystem line 191, Temp line 188) callsPersistenceProviderUtilities.TryConvertToKey. For any type other than string, Guid and int, that usesConvert.ChangeType(value, typeof(TKey), CultureInfo.InvariantCulture)(Essentials/PersistenceProviderUtilities.cs:180), which parses with the invariant culture.In a culture whose decimal separator or date order differs from invariant, a stored key is listed back as a different key. That key does not exist, so
ExistsAsyncandRetrieveAsyncon it miss.Second consequence: because the file name depends on the culture, data stored under one culture cannot be found when the process runs under another (
1.5is stored as1,5.jsonunder de-DE and looked up as1.5.jsonunder en-US).Failure scenario
Output:
Expected:
keys: 1.5, and retrieving that key returns "hello".With
DateTimekeys,new DateTime(2026,3,4,5,6,7)is listed as2026-04-03T05:06:07(day and month swapped).How it was verified
A scratch console app referencing the FileSystem persistence, Native filesystem and Json serialization projects, run against HEAD, produced the output above.
Suggested fix / acceptance criteria
IFormattable.ToString(null, CultureInfo.InvariantCulture)orConvert.ToString(key, CultureInfo.InvariantCulture)), using a round-trippable format ("R"/"O") where it matters. Share one helper between the FileSystem and Temp providers so they cannot drift.CurrentCultureto de-DE, storesdoubleandDateTimekeys, and asserts thatGetAllKeysAsyncreturns exactly the stored keys and thatRetrieveAsyncfinds them afterCurrentCultureis switched to en-US.