Skip to content

Commit 7aea60c

Browse files
committed
feat: decoupled IJsonApiContext from repository wrt updating resources
1 parent 9f7550c commit 7aea60c

File tree

2 files changed

+38
-37
lines changed

2 files changed

+38
-37
lines changed

src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -171,44 +171,34 @@ public virtual async Task<TEntity> CreateAsync(TEntity entity)
171171
/// <inheritdoc />
172172
public void DetachRelationshipPointers(TEntity entity)
173173
{
174-
foreach (var hasOneRelationship in _jsonApiContext.HasOneRelationshipPointers.Get())
175-
{
176-
var hasOne = (HasOneAttribute)hasOneRelationship.Key;
177-
if (hasOne.EntityPropertyName != null)
178-
{
179-
var relatedEntity = entity.GetType().GetProperty(hasOne.EntityPropertyName)?.GetValue(entity);
180-
if (relatedEntity != null)
181-
_context.Entry(relatedEntity).State = EntityState.Detached;
182-
}
183-
else
184-
{
185-
_context.Entry(hasOneRelationship.Value).State = EntityState.Detached;
186-
}
187-
}
188174

189-
foreach (var hasManyRelationship in _jsonApiContext.HasManyRelationshipPointers.Get())
175+
foreach (var relationshipAttr in _jsonApiContext.RelationshipsToUpdate.Keys)
190176
{
191-
var hasMany = (HasManyAttribute)hasManyRelationship.Key;
192-
if (hasMany.EntityPropertyName != null)
177+
if (relationshipAttr is HasOneAttribute hasOneAttr)
193178
{
194-
var relatedList = (IList)entity.GetType().GetProperty(hasMany.EntityPropertyName)?.GetValue(entity);
195-
foreach (var related in relatedList)
196-
{
197-
_context.Entry(related).State = EntityState.Detached;
198-
}
179+
var relationshipValue = GetEntityResourceSeparationValue(entity, hasOneAttr) ?? (IIdentifiable)hasOneAttr.GetValue(entity);
180+
if (relationshipValue == null) continue;
181+
_context.Entry(relationshipValue).State = EntityState.Detached;
182+
199183
}
200-
else
184+
else
201185
{
202-
foreach (var pointer in hasManyRelationship.Value)
186+
IEnumerable<IIdentifiable> relationshipValueList = (IEnumerable<IIdentifiable>)relationshipAttr.GetValue(entity);
187+
/// This adds support for resource-entity separation in the case of one-to-many.
188+
/// todo: currently there is no support for many to many relations.
189+
if (relationshipAttr is HasManyAttribute hasMany)
190+
relationshipValueList = GetEntityResourceSeparationValue(entity, hasMany) ?? relationshipValueList;
191+
if (relationshipValueList == null) continue;
192+
foreach (var pointer in relationshipValueList)
203193
{
204194
_context.Entry(pointer).State = EntityState.Detached;
205195
}
196+
/// detaching has many relationships is not sufficient to
197+
/// trigger a full reload of relationships: the navigation
198+
/// property actually needs to be nulled out, otherwise
199+
/// EF will still add duplicate instances to the collection
200+
relationshipAttr.SetValue(entity, null);
206201
}
207-
208-
// HACK: detaching has many relationships doesn't appear to be sufficient
209-
// the navigation property actually needs to be nulled out, otherwise
210-
// EF adds duplicate instances to the collection
211-
hasManyRelationship.Key.SetValue(entity, null);
212202
}
213203
}
214204

src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,11 @@ private object SetEntityAttributes(
155155
continue;
156156
var convertedValue = ConvertAttrValue(newValue, attr.PropertyInfo.PropertyType);
157157
attr.SetValue(entity, convertedValue);
158-
_jsonApiContext.AttributesToUpdate[attr] = convertedValue;
158+
/// todo: as a part of the process of decoupling JADNC (specifically
159+
/// through the decoupling IJsonApiContext), we now no longer need to
160+
/// store the updated relationship values in this property. For now
161+
/// just assigning null as value, will remove this property later as a whole.
162+
_jsonApiContext.AttributesToUpdate[attr] = null;
159163
}
160164
}
161165

@@ -249,7 +253,10 @@ private void SetHasOneForeignKeyValue(object entity, HasOneAttribute hasOneAttr,
249253
throw new JsonApiException(400, $"Cannot set required relationship identifier '{hasOneAttr.IdentifiablePropertyName}' to null because it is a non-nullable type.");
250254

251255
var convertedValue = TypeHelper.ConvertType(foreignKeyPropertyValue, foreignKeyProperty.PropertyType);
252-
foreignKeyProperty.SetValue(entity, convertedValue);
256+
/// todo: as a part of the process of decoupling JADNC (specifically
257+
/// through the decoupling IJsonApiContext), we now no longer need to
258+
/// store the updated relationship values in this property. For now
259+
/// just assigning null as value, will remove this property later as a whole.
253260
if (convertedValue == null ) _jsonApiContext.HasOneRelationshipPointers.Add(hasOneAttr, null);
254261
}
255262
}
@@ -270,10 +277,11 @@ private void SetHasOneNavigationPropertyValue(object entity, HasOneAttribute has
270277
if (includedRelationshipObject != null)
271278
hasOneAttr.SetValue(entity, includedRelationshipObject);
272279

273-
// we need to store the fact that this relationship was included in the payload
274-
// for EF, the repository will use these pointers to make ensure we don't try to
275-
// create resources if they already exist, we just need to create the relationship
276-
_jsonApiContext.HasOneRelationshipPointers.Add(hasOneAttr, includedRelationshipObject);
280+
/// todo: as a part of the process of decoupling JADNC (specifically
281+
/// through the decoupling IJsonApiContext), we now no longer need to
282+
/// store the updated relationship values in this property. For now
283+
/// just assigning null as value, will remove this property later as a whole.
284+
_jsonApiContext.HasOneRelationshipPointers.Add(hasOneAttr, null);
277285
}
278286
}
279287

@@ -300,8 +308,11 @@ private object SetHasManyRelationship(object entity,
300308
var convertedCollection = TypeHelper.ConvertCollection(relatedResources, attr.Type);
301309

302310
attr.SetValue(entity, convertedCollection);
303-
//_jsonApiContext.RelationshipsToUpdate[attr] = convertedCollection; // WHAT exactly is the use of these two different collections..?
304-
_jsonApiContext.HasManyRelationshipPointers.Add(attr, convertedCollection);
311+
/// todo: as a part of the process of decoupling JADNC (specifically
312+
/// through the decoupling IJsonApiContext), we now no longer need to
313+
/// store the updated relationship values in this property. For now
314+
/// just assigning null as value, will remove this property later as a whole.
315+
_jsonApiContext.HasManyRelationshipPointers.Add(attr, null);
305316
}
306317

307318
return entity;

0 commit comments

Comments
 (0)