Skip to content

Commit

Permalink
Fix cache key when creating multi-map delegate for types with multipl…
Browse files Browse the repository at this point in the history
…e key properties
  • Loading branch information
henkmollema committed Aug 23, 2024
1 parent 9a43fe6 commit d07c310
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 9 deletions.
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<Copyright>Copyright © Henk Mollema 2014</Copyright>
<VersionPrefix>3.3.2</VersionPrefix>
<VersionPrefix>3.3.3</VersionPrefix>
<Authors>Henk Mollema</Authors>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
Expand Down
20 changes: 12 additions & 8 deletions src/Dommel/AutoMultiMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -705,19 +705,23 @@ internal static Delegate CreateMapDelegate<T1, T2, T3, T4, T5, T6, T7, TReturn>(
.ToArray();

var targetProperties = typeof(T1).GetProperties();
var keyProperty = Resolvers.KeyProperties(typeof(T1)).First().Property;
var keyProperties = Resolvers.KeyProperties(typeof(T1)).Select(x => x.Property);

// Create unique number from two integers
// https://stackoverflow.com/a/14652569
static int Pair(int a, int b) => (int)(((a + b) * (a + b + 1) * 0.5) + b);

T1 GetOrAdd(T1 target)
{
// Populate the dictionary with cached items keyed by the hash code
// of the value of the primary key property. This way multi mapping
// one-to-many relations don't produce multiple instances of the
// same parent record.
var id = keyProperty!.GetValue(target)!.GetHashCode();
if (!results.TryGetValue(id, out var cachedItem))
// Populate the dictionary with cached items keyed by the hash code of
// the value of the primary key properties. This way multi mapping one-to-many
// relations don't produce multiple instances of the same parent record.
// Use paired hash codes of all key properties as cache key.
var cacheKey = keyProperties.Aggregate(0, (x, prop) => Pair(x, prop.GetValue(target)!.GetHashCode()));
if (!results.TryGetValue(cacheKey, out var cachedItem))
{
cachedItem = target;
results[id] = cachedItem;
results[cacheKey] = cachedItem;
}
return cachedItem;
}
Expand Down

0 comments on commit d07c310

Please sign in to comment.