@@ -29,7 +29,7 @@ public DefaultEntityRepository(
29
29
public DefaultEntityRepository (
30
30
ILoggerFactory loggerFactory ,
31
31
IJsonApiContext jsonApiContext ,
32
- IDbContextResolver contextResolver ,
32
+ IDbContextResolver contextResolver ,
33
33
ResourceDefinition < TEntity > resourceDefinition = null )
34
34
: base ( loggerFactory , jsonApiContext , contextResolver , resourceDefinition )
35
35
{ }
@@ -222,14 +222,20 @@ public virtual async Task<TEntity> UpdateAsync(TId id, TEntity entity)
222
222
223
223
if ( _jsonApiContext . RelationshipsToUpdate . Any ( ) )
224
224
{
225
+ /// First attach all targeted relationships to the dbcontext.
226
+ /// This takes into account that some of these entities are
227
+ /// already attached in the dbcontext
225
228
AttachRelationships ( oldEntity ) ;
226
- AssignRelationshipValues ( oldEntity , update : true ) ;
229
+ /// load the current state of the relationship to support complete-replacement
230
+ LoadCurrentRelationships ( oldEntity ) ;
231
+ /// assign the actual relationship values.
232
+ AssignRelationshipValues ( oldEntity ) ;
227
233
}
228
234
await _context . SaveChangesAsync ( ) ;
229
235
return oldEntity ;
230
236
}
231
-
232
237
/// <inheritdoc />
238
+
233
239
public async Task UpdateRelationshipsAsync ( object parent , RelationshipAttribute relationship , IEnumerable < string > relationshipIds )
234
240
{
235
241
// TODO: it would be better to let this be determined within the relationship attribute...
@@ -373,30 +379,52 @@ private void AttachHasManyAndHasManyThroughPointers(TEntity entity)
373
379
}
374
380
375
381
/// <summary>
376
- /// todo: comments
382
+ /// Before assigning new relationship values (updateasync), we need to
383
+ /// attach load the current relationship state into the dbcontext, else
384
+ /// there won't be a complete-replace for one-to-many and many-to-many.
385
+ /// </summary>
386
+ /// <param name="oldEntity">Old entity.</param>
387
+ protected void LoadCurrentRelationships ( TEntity oldEntity )
388
+ {
389
+ foreach ( var relationshipEntry in _jsonApiContext . RelationshipsToUpdate )
390
+ {
391
+ var relationshipValue = relationshipEntry . Value ;
392
+ if ( relationshipEntry . Key is HasManyThroughAttribute throughAttribute )
393
+ {
394
+ _context . Entry ( oldEntity ) . Collection ( throughAttribute . InternalThroughName ) . Load ( ) ;
395
+
396
+ }
397
+ else if ( relationshipEntry . Key is HasManyAttribute hasManyAttribute )
398
+ {
399
+ _context . Entry ( oldEntity ) . Collection ( hasManyAttribute . InternalRelationshipName ) . Load ( ) ;
400
+ }
401
+ }
402
+ }
403
+
404
+ /// <summary>
405
+ /// assigns relationships that were set in the request to the target entity of the request
406
+ /// todo: partially remove dependency on IJsonApiContext here: it is fine to
407
+ /// retrieve from the context WHICH relationships to update, but the actual values should
408
+ /// come from the context.
377
409
/// </summary>
378
- protected void AssignRelationshipValues ( TEntity oldEntity , bool update = false )
410
+ protected void AssignRelationshipValues ( TEntity oldEntity )
379
411
{
380
412
foreach ( var relationshipEntry in _jsonApiContext . RelationshipsToUpdate )
381
413
{
382
414
var relationshipValue = relationshipEntry . Value ;
383
415
if ( relationshipEntry . Key is HasManyThroughAttribute throughAttribute )
384
416
{
385
- // load relations to enforce complete replace in case of patch
386
- if ( update ) _context . Entry ( oldEntity ) . Collection ( throughAttribute . InternalThroughName ) . Load ( ) ;
387
417
AssignHasManyThrough ( oldEntity , throughAttribute , ( IList ) relationshipValue ) ;
388
418
}
389
419
else if ( relationshipEntry . Key is HasManyAttribute hasManyAttribute )
390
420
{
391
- // load relations to enforce complete replace
392
- if ( update ) _context . Entry ( oldEntity ) . Collection ( hasManyAttribute . InternalRelationshipName ) . Load ( ) ;
393
421
// todo: need to load inverse relationship here, see issue #502
394
- hasManyAttribute . SetValue ( oldEntity , relationshipValue ) ;
422
+ hasManyAttribute . SetValue ( oldEntity , relationshipValue ) ;
395
423
}
396
424
else if ( relationshipEntry . Key is HasOneAttribute hasOneAttribute )
397
425
{
398
426
// todo: need to load inverse relationship here, see issue #502
399
- if ( update ) hasOneAttribute . SetValue ( oldEntity , relationshipValue ) ;
427
+ hasOneAttribute . SetValue ( oldEntity , relationshipValue ) ;
400
428
}
401
429
}
402
430
}
0 commit comments