@@ -29,7 +29,7 @@ public DefaultEntityRepository(
2929 public DefaultEntityRepository (
3030 ILoggerFactory loggerFactory ,
3131 IJsonApiContext jsonApiContext ,
32- IDbContextResolver contextResolver ,
32+ IDbContextResolver contextResolver ,
3333 ResourceDefinition < TEntity > resourceDefinition = null )
3434 : base ( loggerFactory , jsonApiContext , contextResolver , resourceDefinition )
3535 { }
@@ -222,14 +222,20 @@ public virtual async Task<TEntity> UpdateAsync(TId id, TEntity entity)
222222
223223 if ( _jsonApiContext . RelationshipsToUpdate . Any ( ) )
224224 {
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
225228 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 ) ;
227233 }
228234 await _context . SaveChangesAsync ( ) ;
229235 return oldEntity ;
230236 }
231-
232237 /// <inheritdoc />
238+
233239 public async Task UpdateRelationshipsAsync ( object parent , RelationshipAttribute relationship , IEnumerable < string > relationshipIds )
234240 {
235241 // TODO: it would be better to let this be determined within the relationship attribute...
@@ -373,30 +379,52 @@ private void AttachHasManyAndHasManyThroughPointers(TEntity entity)
373379 }
374380
375381 /// <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.
377409 /// </summary>
378- protected void AssignRelationshipValues ( TEntity oldEntity , bool update = false )
410+ protected void AssignRelationshipValues ( TEntity oldEntity )
379411 {
380412 foreach ( var relationshipEntry in _jsonApiContext . RelationshipsToUpdate )
381413 {
382414 var relationshipValue = relationshipEntry . Value ;
383415 if ( relationshipEntry . Key is HasManyThroughAttribute throughAttribute )
384416 {
385- // load relations to enforce complete replace in case of patch
386- if ( update ) _context . Entry ( oldEntity ) . Collection ( throughAttribute . InternalThroughName ) . Load ( ) ;
387417 AssignHasManyThrough ( oldEntity , throughAttribute , ( IList ) relationshipValue ) ;
388418 }
389419 else if ( relationshipEntry . Key is HasManyAttribute hasManyAttribute )
390420 {
391- // load relations to enforce complete replace
392- if ( update ) _context . Entry ( oldEntity ) . Collection ( hasManyAttribute . InternalRelationshipName ) . Load ( ) ;
393421 // todo: need to load inverse relationship here, see issue #502
394- hasManyAttribute . SetValue ( oldEntity , relationshipValue ) ;
422+ hasManyAttribute . SetValue ( oldEntity , relationshipValue ) ;
395423 }
396424 else if ( relationshipEntry . Key is HasOneAttribute hasOneAttribute )
397425 {
398426 // todo: need to load inverse relationship here, see issue #502
399- if ( update ) hasOneAttribute . SetValue ( oldEntity , relationshipValue ) ;
427+ hasOneAttribute . SetValue ( oldEntity , relationshipValue ) ;
400428 }
401429 }
402430 }
0 commit comments