Skip to content

Commit 6bf8523

Browse files
committed
Update FilterEntry.cs
1 parent a27fe47 commit 6bf8523

1 file changed

Lines changed: 47 additions & 80 deletions

File tree

src/GraphQL.EntityFramework/Filters/FilterEntry.cs

Lines changed: 47 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -33,117 +33,66 @@ public FieldProjectionInfo AddRequirements(
3333
return projection;
3434
}
3535

36-
// Separate simple fields and navigation paths
37-
var scalarFieldsToAdd = new List<string>();
38-
var navigationPaths = new Dictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase);
36+
var mergedScalars = new HashSet<string>(projection.ScalarFields, StringComparer.OrdinalIgnoreCase);
37+
var navRequirements = new Dictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase);
3938

4039
foreach (var field in requiredPropertyNames)
4140
{
42-
if (field.Contains('.'))
41+
var dotIndex = field.IndexOf('.');
42+
if (dotIndex < 0)
4343
{
44-
// Navigation path like "Parent.Id"
45-
var parts = field.Split('.', 2);
46-
var navName = parts[0];
47-
var navProperty = parts[1];
48-
49-
if (!navigationPaths.TryGetValue(navName, out var properties))
44+
// Scalar field - skip navigation property names
45+
if (FindNavigation(navigationProperties, field) == null)
5046
{
51-
properties = new(StringComparer.OrdinalIgnoreCase);
52-
navigationPaths[navName] = properties;
47+
mergedScalars.Add(field);
5348
}
5449

55-
// Only add if it doesn't contain further dots (single-level navigation)
56-
if (!navProperty.Contains('.'))
57-
{
58-
properties.Add(navProperty);
59-
}
50+
continue;
6051
}
61-
else
62-
{
63-
// Simple field - check if it's a navigation property
64-
var isNavigation = navigationProperties?.ContainsKey(field) == true;
65-
66-
if (isNavigation ||
67-
projection.ScalarFields.Contains(field) ||
68-
projection.KeyNames?.Contains(field, StringComparer.OrdinalIgnoreCase) == true)
69-
{
70-
// Skip navigation names - they'll be handled via navigation paths
71-
continue;
72-
}
7352

74-
scalarFieldsToAdd.Add(field);
75-
}
76-
}
53+
var navProperty = field[(dotIndex + 1)..];
7754

78-
// Merge scalar fields
79-
var mergedScalars = new HashSet<string>(projection.ScalarFields, StringComparer.OrdinalIgnoreCase);
80-
foreach (var field in scalarFieldsToAdd)
81-
{
82-
mergedScalars.Add(field);
83-
}
84-
85-
// Merge navigations
86-
var infos = projection.Navigations;
87-
Dictionary<string, NavigationProjectionInfo> mergedNavigations;
88-
if (infos == null)
89-
{
90-
mergedNavigations = [];
91-
}
92-
else
93-
{
94-
mergedNavigations = new(infos);
95-
}
96-
97-
// Process navigation paths from filter fields
98-
foreach (var (navName, requiredProps) in navigationPaths)
99-
{
100-
// Skip if no navigation metadata available for this entity type
101-
if (navigationProperties == null)
55+
// Only handle single-level navigation paths
56+
if (navProperty.Contains('.'))
10257
{
10358
continue;
10459
}
10560

106-
// Try to find the navigation - use case-insensitive search
107-
Navigation? navMetadata = null;
108-
foreach (var (key, value) in navigationProperties)
61+
var navName = field[..dotIndex];
62+
if (!navRequirements.TryGetValue(navName, out var props))
10963
{
110-
if (string.Equals(key, navName, StringComparison.OrdinalIgnoreCase))
111-
{
112-
navMetadata = value;
113-
break;
114-
}
64+
props = new(StringComparer.OrdinalIgnoreCase);
65+
navRequirements[navName] = props;
11566
}
11667

68+
props.Add(navProperty);
69+
}
70+
71+
// Merge navigation requirements
72+
var mergedNavigations = projection.Navigations != null
73+
? new Dictionary<string, NavigationProjectionInfo>(projection.Navigations)
74+
: new Dictionary<string, NavigationProjectionInfo>();
75+
76+
foreach (var (navName, requiredProps) in navRequirements)
77+
{
78+
var navMetadata = FindNavigation(navigationProperties, navName);
11779
if (navMetadata == null)
11880
{
11981
continue;
12082
}
12183

122-
var navType = navMetadata.Type;
12384
if (mergedNavigations.TryGetValue(navName, out var existingNav))
12485
{
125-
// Navigation exists in GraphQL query - add filter-required properties to its projection
12686
var updatedScalars = new HashSet<string>(existingNav.Projection.ScalarFields, StringComparer.OrdinalIgnoreCase);
127-
foreach (var prop in requiredProps)
128-
{
129-
updatedScalars.Add(prop);
130-
}
131-
132-
var updatedProjection = existingNav.Projection with
133-
{
134-
ScalarFields = updatedScalars
135-
};
87+
updatedScalars.UnionWith(requiredProps);
13688
mergedNavigations[navName] = existingNav with
13789
{
138-
Projection = updatedProjection
90+
Projection = existingNav.Projection with { ScalarFields = updatedScalars }
13991
};
14092
}
14193
else
14294
{
143-
// Create navigation projection for filter-only navigations.
144-
// Don't include key/FK columns - the filter only needs the specific properties it accesses.
145-
var navProjection = new FieldProjectionInfo(requiredProps, null, null, null);
146-
mergedNavigations[navName] = new(navType, navMetadata.IsCollection, navProjection);
95+
mergedNavigations[navName] = new(navMetadata.Type, navMetadata.IsCollection, new(requiredProps, null, null, null));
14796
}
14897
}
14998

@@ -154,6 +103,24 @@ public FieldProjectionInfo AddRequirements(
154103
};
155104
}
156105

106+
static Navigation? FindNavigation(IReadOnlyDictionary<string, Navigation>? properties, string name)
107+
{
108+
if (properties == null)
109+
{
110+
return null;
111+
}
112+
113+
foreach (var (key, value) in properties)
114+
{
115+
if (string.Equals(key, name, StringComparison.OrdinalIgnoreCase))
116+
{
117+
return value;
118+
}
119+
}
120+
121+
return null;
122+
}
123+
157124
public Task<bool> ShouldIncludeWithProjection(
158125
object userContext,
159126
TDbContext data,

0 commit comments

Comments
 (0)