|
1 | 1 | using System;
|
2 | 2 | using System.Collections.Generic;
|
| 3 | +using System.Collections.Immutable; |
3 | 4 | using System.Linq;
|
4 | 5 | using System.Net;
|
5 | 6 | using System.Reflection;
|
@@ -185,10 +186,48 @@ public async Task<TResource> GetAsync(TId id, CancellationToken cancellationToke
|
185 | 186 | }
|
186 | 187 |
|
187 | 188 | /// <inheritdoc />
|
188 |
| - public Task AddToToManyRelationshipAsync(TId primaryId, string relationshipName, ISet<IIdentifiable> secondaryResourceIds, |
| 189 | + public async Task AddToToManyRelationshipAsync(TId primaryId, string relationshipName, ISet<IIdentifiable> secondaryResourceIds, |
189 | 190 | CancellationToken cancellationToken)
|
190 | 191 | {
|
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); |
192 | 231 | }
|
193 | 232 |
|
194 | 233 | /// <inheritdoc />
|
@@ -423,14 +462,6 @@ protected virtual async Task GetIncludedElementAsync(IReadOnlyCollection<IIdenti
|
423 | 462 | });
|
424 | 463 | }
|
425 | 464 |
|
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 |
| - |
434 | 465 | string relationshipName = includeElementExpression.Relationship.PublicName;
|
435 | 466 |
|
436 | 467 | foreach (var primaryResource in primaryResources)
|
@@ -480,15 +511,6 @@ protected virtual async Task GetIncludedElementAsync(IReadOnlyCollection<IIdenti
|
480 | 511 | });
|
481 | 512 | }
|
482 | 513 |
|
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 |
| - |
492 | 514 | // Get the HasForeignKey attribute corresponding to the relationship, if any.
|
493 | 515 | var foreignKeyAttribute = (NoSqlHasForeignKeyAttribute?)Attribute.GetCustomAttribute(
|
494 | 516 | relationshipAttribute.Property, typeof(NoSqlHasForeignKeyAttribute));
|
@@ -630,15 +652,6 @@ private static void AssertPrimaryResourceTypeInJsonApiRequestIsNotNull([SysNotNu
|
630 | 652 | }
|
631 | 653 | }
|
632 | 654 |
|
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 |
| - |
642 | 655 | /// <summary>
|
643 | 656 | /// Gets the <see cref="string" /> value of the named property.
|
644 | 657 | /// </summary>
|
|
0 commit comments