Skip to content

Commit 1ef4f50

Browse files
Enhance NoSqlResourceService
1 parent 443aa98 commit 1ef4f50

File tree

3 files changed

+42
-76
lines changed

3 files changed

+42
-76
lines changed

src/JsonApiDotNetCore/Queries/NoSqlQueryLayerComposer.cs

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using System;
21
using System.Collections.Generic;
32
using System.Collections.Immutable;
43
using System.Linq;
@@ -259,26 +258,11 @@ public override bool VisitComparison(ComparisonExpression expression, object? ar
259258
/// <inheritdoc />
260259
public override bool VisitResourceFieldChain(ResourceFieldChainExpression expression, object? argument)
261260
{
262-
_isSimpleFilterExpression &= expression.Fields.All(IsFieldSupported);
261+
_isSimpleFilterExpression &= expression.Fields.All(field => field is AttrAttribute);
263262

264263
return _isSimpleFilterExpression;
265264
}
266265

267-
private static bool IsFieldSupported(ResourceFieldAttribute field)
268-
{
269-
return field switch
270-
{
271-
AttrAttribute => true,
272-
HasManyAttribute hasMany when HasOwnsManyAttribute(hasMany) => true,
273-
_ => false
274-
};
275-
}
276-
277-
private static bool HasOwnsManyAttribute(ResourceFieldAttribute field)
278-
{
279-
return Attribute.GetCustomAttribute(field.Property, typeof(NoSqlOwnsManyAttribute)) is not null;
280-
}
281-
282266
/// <inheritdoc />
283267
public override bool VisitLogical(LogicalExpression expression, object? argument)
284268
{

src/JsonApiDotNetCore/Resources/Annotations/NoSqlOwnsManyAttribute.cs

Lines changed: 0 additions & 31 deletions
This file was deleted.

src/JsonApiDotNetCore/Services/NoSqlResourceService.cs

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Collections.Immutable;
34
using System.Linq;
45
using System.Net;
56
using System.Reflection;
@@ -185,10 +186,48 @@ public async Task<TResource> GetAsync(TId id, CancellationToken cancellationToke
185186
}
186187

187188
/// <inheritdoc />
188-
public Task AddToToManyRelationshipAsync(TId primaryId, string relationshipName, ISet<IIdentifiable> secondaryResourceIds,
189+
public async Task AddToToManyRelationshipAsync(TId primaryId, string relationshipName, ISet<IIdentifiable> secondaryResourceIds,
189190
CancellationToken cancellationToken)
190191
{
191-
return _resourceService.AddToToManyRelationshipAsync(primaryId, relationshipName, secondaryResourceIds, cancellationToken);
192+
RelationshipAttribute? relationship = _request.Relationship;
193+
194+
if (relationship == null)
195+
{
196+
throw new RelationshipNotFoundException(relationshipName, _request.PrimaryResourceType!.PublicName);
197+
}
198+
199+
if (!secondaryResourceIds.Any())
200+
{
201+
return;
202+
}
203+
204+
ResourceType resourceType = relationship.RightType;
205+
206+
var targetAttribute = new ResourceFieldChainExpression(resourceType.FindAttributeByPropertyName(nameof(IIdentifiable<object>.Id))!);
207+
208+
ImmutableHashSet<LiteralConstantExpression> idConstants =
209+
secondaryResourceIds.Select(identifiable => new LiteralConstantExpression(identifiable.StringId!)).ToImmutableHashSet();
210+
211+
var queryLayer = new QueryLayer(resourceType)
212+
{
213+
Filter = idConstants.Count > 1
214+
? new AnyExpression(targetAttribute, idConstants)
215+
: new ComparisonExpression(ComparisonOperator.Equals, targetAttribute, idConstants.Single())
216+
};
217+
218+
IReadOnlyCollection<IIdentifiable> secondaryResources = await _repositoryAccessor.GetAsync(resourceType, queryLayer, cancellationToken);
219+
220+
ImmutableHashSet<IIdentifiable> missingResources = secondaryResourceIds
221+
.Where(requestResource => secondaryResources.All(resource => resource.StringId != requestResource.StringId)).ToImmutableHashSet();
222+
223+
if (missingResources.Any())
224+
{
225+
IIdentifiable missingResource = missingResources.First();
226+
227+
throw new ResourceNotFoundException(missingResource.StringId!, resourceType.PublicName);
228+
}
229+
230+
await _resourceService.AddToToManyRelationshipAsync(primaryId, relationshipName, secondaryResourceIds, cancellationToken);
192231
}
193232

194233
/// <inheritdoc />
@@ -423,14 +462,6 @@ protected virtual async Task GetIncludedElementAsync(IReadOnlyCollection<IIdenti
423462
});
424463
}
425464

426-
PropertyInfo property = includeElementExpression.Relationship.Property;
427-
var ownsMany = Attribute.GetCustomAttribute(property, typeof(NoSqlOwnsManyAttribute));
428-
429-
if (ownsMany is not null)
430-
{
431-
return;
432-
}
433-
434465
string relationshipName = includeElementExpression.Relationship.PublicName;
435466

436467
foreach (var primaryResource in primaryResources)
@@ -480,15 +511,6 @@ protected virtual async Task GetIncludedElementAsync(IReadOnlyCollection<IIdenti
480511
});
481512
}
482513

483-
// Check whether the secondary resource is owned by the primary resource.
484-
PropertyInfo property = relationshipAttribute.Property;
485-
var ownsMany = Attribute.GetCustomAttribute(property, typeof(NoSqlOwnsManyAttribute));
486-
487-
if (ownsMany is not null)
488-
{
489-
return relationshipAttribute.GetValue(primaryResource);
490-
}
491-
492514
// Get the HasForeignKey attribute corresponding to the relationship, if any.
493515
var foreignKeyAttribute = (NoSqlHasForeignKeyAttribute?)Attribute.GetCustomAttribute(
494516
relationshipAttribute.Property, typeof(NoSqlHasForeignKeyAttribute));
@@ -630,15 +652,6 @@ private static void AssertPrimaryResourceTypeInJsonApiRequestIsNotNull([SysNotNu
630652
}
631653
}
632654

633-
[AssertionMethod]
634-
private static void AssertRelationshipInJsonApiRequestIsNotNull([SysNotNull] RelationshipAttribute? relationship)
635-
{
636-
if (relationship is null)
637-
{
638-
throw new InvalidOperationException($"Expected {nameof(IJsonApiRequest)}.{nameof(IJsonApiRequest.Relationship)} not to be null at this point.");
639-
}
640-
}
641-
642655
/// <summary>
643656
/// Gets the <see cref="string" /> value of the named property.
644657
/// </summary>

0 commit comments

Comments
 (0)