11
11
using JsonApiDotNetCore . Services ;
12
12
using Microsoft . EntityFrameworkCore ;
13
13
using Microsoft . Extensions . Logging ;
14
-
15
14
namespace JsonApiDotNetCore . Data
16
15
{
17
16
/// <inheritdoc />
@@ -30,7 +29,7 @@ public DefaultEntityRepository(
30
29
public DefaultEntityRepository (
31
30
ILoggerFactory loggerFactory ,
32
31
IJsonApiContext jsonApiContext ,
33
- IDbContextResolver contextResolver ,
32
+ IDbContextResolver contextResolver ,
34
33
ResourceDefinition < TEntity > resourceDefinition = null )
35
34
: base ( loggerFactory , jsonApiContext , contextResolver , resourceDefinition )
36
35
{ }
@@ -51,7 +50,6 @@ public class DefaultEntityRepository<TEntity, TId>
51
50
private readonly IJsonApiContext _jsonApiContext ;
52
51
private readonly IGenericProcessorFactory _genericProcessorFactory ;
53
52
private readonly ResourceDefinition < TEntity > _resourceDefinition ;
54
-
55
53
public DefaultEntityRepository (
56
54
IJsonApiContext jsonApiContext ,
57
55
IDbContextResolver contextResolver ,
@@ -102,7 +100,6 @@ public virtual IQueryable<TEntity> Filter(IQueryable<TEntity> entities, FilterQu
102
100
return defaultQueryFilter ( entities , filterQuery ) ;
103
101
}
104
102
}
105
-
106
103
return entities . Filter ( _jsonApiContext , filterQuery ) ;
107
104
}
108
105
@@ -124,7 +121,6 @@ public virtual IQueryable<TEntity> Sort(IQueryable<TEntity> entities, List<SortQ
124
121
}
125
122
}
126
123
}
127
-
128
124
return entities ;
129
125
}
130
126
@@ -149,22 +145,17 @@ public virtual async Task<TEntity> GetAndIncludeAsync(TId id, string relationshi
149
145
public virtual async Task < TEntity > CreateAsync ( TEntity entity )
150
146
{
151
147
AttachRelationships ( entity ) ;
152
- foreach ( var relationshipEntry in _jsonApiContext . RelationshipsToUpdate )
153
- {
154
- var relationshipValue = relationshipEntry . Value ;
155
- if ( relationshipEntry . Key is HasManyThroughAttribute throughAttribute )
156
- {
157
- AssignHasManyThrough ( entity , throughAttribute , ( IList ) relationshipValue ) ;
158
- }
159
- }
160
-
148
+ AssignRelationshipValues ( entity ) ;
161
149
_dbSet . Add ( entity ) ;
162
150
163
151
await _context . SaveChangesAsync ( ) ;
164
152
165
153
return entity ;
166
154
}
167
155
156
+ /// <summary>
157
+
158
+ /// </summary>
168
159
protected virtual void AttachRelationships ( TEntity entity = null )
169
160
{
170
161
AttachHasManyAndHasManyThroughPointers ( entity ) ;
@@ -232,27 +223,7 @@ public virtual async Task<TEntity> UpdateAsync(TId id, TEntity entity)
232
223
if ( _jsonApiContext . RelationshipsToUpdate . Any ( ) )
233
224
{
234
225
AttachRelationships ( oldEntity ) ;
235
- foreach ( var relationshipEntry in _jsonApiContext . RelationshipsToUpdate )
236
- {
237
- var relationshipValue = relationshipEntry . Value ;
238
- if ( relationshipEntry . Key is HasManyThroughAttribute throughAttribute )
239
- {
240
- // load relations to enforce complete replace
241
- await _context . Entry ( oldEntity ) . Collection ( throughAttribute . InternalThroughName ) . LoadAsync ( ) ;
242
- AssignHasManyThrough ( oldEntity , throughAttribute , ( IList ) relationshipValue ) ;
243
- } else if ( relationshipEntry . Key is HasManyAttribute hasManyAttribute )
244
- {
245
- // load relations to enforce complete replace
246
- await _context . Entry ( oldEntity ) . Collection ( hasManyAttribute . InternalRelationshipName ) . LoadAsync ( ) ;
247
- // todo: need to load inverse relationship here, see issue #502
248
- hasManyAttribute . SetValue ( oldEntity , relationshipValue ) ;
249
- }
250
- else if ( relationshipEntry . Key is HasOneAttribute hasOneAttribute )
251
- {
252
- // todo: need to load inverse relationship here, see issue #502
253
- hasOneAttribute . SetValue ( oldEntity , relationshipValue ) ;
254
- }
255
- }
226
+ AssignRelationshipValues ( oldEntity , update : true ) ;
256
227
}
257
228
await _context . SaveChangesAsync ( ) ;
258
229
return oldEntity ;
@@ -273,18 +244,14 @@ public async Task UpdateRelationshipsAsync(object parent, RelationshipAttribute
273
244
await genericProcessor . UpdateRelationshipsAsync ( parent , relationship , relationshipIds ) ;
274
245
}
275
246
247
+
276
248
/// <inheritdoc />
277
249
public virtual async Task < bool > DeleteAsync ( TId id )
278
250
{
279
251
var entity = await GetAsync ( id ) ;
280
-
281
- if ( entity == null )
282
- return false ;
283
-
252
+ if ( entity == null ) return false ;
284
253
_dbSet . Remove ( entity ) ;
285
-
286
254
await _context . SaveChangesAsync ( ) ;
287
-
288
255
return true ;
289
256
}
290
257
@@ -392,14 +359,45 @@ private void AttachHasManyAndHasManyThroughPointers(TEntity entity)
392
359
393
360
if ( pointers == null ) continue ;
394
361
bool alreadyTracked = false ;
362
+ Type entityType = null ;
395
363
var newPointerCollection = pointers . Select ( pointer =>
396
364
{
365
+ entityType = pointer . GetType ( ) ;
397
366
var tracked = AttachOrGetTracked ( pointer ) ;
398
367
if ( tracked != null ) alreadyTracked = true ;
399
- return tracked ?? pointer ;
400
- } ) . Cast ( attribute . Type ) ;
368
+ return Convert . ChangeType ( tracked ?? pointer , entityType ) ;
369
+ } ) . ToList ( ) . Cast ( entityType ) ;
401
370
402
- if ( alreadyTracked ) relationships [ attribute ] = ( IList ) newPointerCollection ;
371
+ if ( alreadyTracked || pointers != relationships [ attribute ] ) relationships [ attribute ] = ( IList ) newPointerCollection ;
372
+ }
373
+ }
374
+
375
+ /// <summary>
376
+ /// todo: comments
377
+ /// </summary>
378
+ protected void AssignRelationshipValues ( TEntity oldEntity , bool update = false )
379
+ {
380
+ foreach ( var relationshipEntry in _jsonApiContext . RelationshipsToUpdate )
381
+ {
382
+ var relationshipValue = relationshipEntry . Value ;
383
+ if ( relationshipEntry . Key is HasManyThroughAttribute throughAttribute )
384
+ {
385
+ // load relations to enforce complete replace in case of patch
386
+ if ( update ) _context . Entry ( oldEntity ) . Collection ( throughAttribute . InternalThroughName ) . Load ( ) ;
387
+ AssignHasManyThrough ( oldEntity , throughAttribute , ( IList ) relationshipValue ) ;
388
+ }
389
+ else if ( relationshipEntry . Key is HasManyAttribute hasManyAttribute )
390
+ {
391
+ // load relations to enforce complete replace
392
+ if ( update ) _context . Entry ( oldEntity ) . Collection ( hasManyAttribute . InternalRelationshipName ) . Load ( ) ;
393
+ // todo: need to load inverse relationship here, see issue #502
394
+ hasManyAttribute . SetValue ( oldEntity , relationshipValue ) ;
395
+ }
396
+ else if ( relationshipEntry . Key is HasOneAttribute hasOneAttribute )
397
+ {
398
+ // todo: need to load inverse relationship here, see issue #502
399
+ if ( update ) hasOneAttribute . SetValue ( oldEntity , relationshipValue ) ;
400
+ }
403
401
}
404
402
}
405
403
@@ -409,7 +407,7 @@ private void AttachHasManyAndHasManyThroughPointers(TEntity entity)
409
407
/// use the join table (ArticleTags). This methods assigns the relationship value to entity
410
408
/// by taking care of that
411
409
/// </summary>
412
- protected void AssignHasManyThrough ( TEntity entity , HasManyThroughAttribute hasManyThrough , IList relationshipValue )
410
+ private void AssignHasManyThrough ( TEntity entity , HasManyThroughAttribute hasManyThrough , IList relationshipValue )
413
411
{
414
412
var pointers = relationshipValue . Cast < IIdentifiable > ( ) ;
415
413
var throughRelationshipCollection = Activator . CreateInstance ( hasManyThrough . ThroughProperty . PropertyType ) as IList ;
@@ -438,7 +436,7 @@ private void AttachHasOnePointers(TEntity entity)
438
436
var pointer = GetRelationshipPointer ( entity , attribute ) ?? relationships [ attribute ] ;
439
437
if ( pointer == null ) return ;
440
438
var tracked = AttachOrGetTracked ( pointer ) ;
441
- if ( tracked != null ) relationships [ attribute ] = tracked ;
439
+ if ( tracked != null || pointer != relationships [ attribute ] ) relationships [ attribute ] = tracked ?? pointer ;
442
440
}
443
441
}
444
442
0 commit comments