Skip to content

Commit 6f551c3

Browse files
committed
feat: introduced EntityHashSetDiff instead of EntityDiff
1 parent a82a241 commit 6f551c3

File tree

8 files changed

+30
-44
lines changed

8 files changed

+30
-44
lines changed

src/JsonApiDotNetCore/Hooks/Execution/EntityDiffs.cs renamed to src/JsonApiDotNetCore/Hooks/Execution/EntityHashSetDiff.cs

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Collections;
33
using System.Collections.Generic;
4-
using System.Collections.ObjectModel;
54
using System.Linq;
65
using JsonApiDotNetCore.Internal;
76
using JsonApiDotNetCore.Models;
@@ -15,68 +14,55 @@ namespace JsonApiDotNetCore.Hooks
1514
/// Also contains information about updated relationships through
1615
/// implementation of IRelationshipsDictionary<typeparamref name="TResource"/>>
1716
/// </summary>
18-
public interface IEntityDiffs<TResource> : IEnumerable<EntityDiffPair<TResource>> where TResource : class, IIdentifiable
17+
public interface IEntityHashSetDiff<TResource> : IEntityHashSet<TResource> where TResource : class, IIdentifiable
1918
{
2019
/// <summary>
21-
/// The database values of the resources affected by the request.
20+
/// Iterates over diffs, which is the affected entity from the request
21+
/// with their associated current value from the database.
2222
/// </summary>
23-
HashSet<TResource> DatabaseValues { get; }
24-
25-
/// <summary>
26-
/// The resources that were affected by the request.
27-
/// </summary>
28-
EntityHashSet<TResource> Entities { get; }
29-
23+
IEnumerator<EntityDiffPair<TResource>> GetDiffs();
24+
3025
}
3126

3227
/// <inheritdoc />
33-
public class EntityDiffs<TResource> : IEntityDiffs<TResource> where TResource : class, IIdentifiable
28+
public class EntityHashSetDiff<TResource> : EntityHashSet<TResource>, IEntityHashSetDiff<TResource> where TResource : class, IIdentifiable
3429
{
35-
/// <inheritdoc />
36-
public HashSet<TResource> DatabaseValues { get => _databaseValues ?? ThrowNoDbValuesError(); }
37-
/// <inheritdoc />
38-
public EntityHashSet<TResource> Entities { get; private set; }
39-
4030
private readonly HashSet<TResource> _databaseValues;
4131
private readonly bool _databaseValuesLoaded;
4232

43-
public EntityDiffs(HashSet<TResource> requestEntities,
33+
public EntityHashSetDiff(HashSet<TResource> requestEntities,
4434
HashSet<TResource> databaseEntities,
45-
Dictionary<RelationshipAttribute, HashSet<TResource>> relationships)
35+
Dictionary<RelationshipAttribute, HashSet<TResource>> relationships)
36+
: base(requestEntities, relationships)
4637
{
47-
Entities = new EntityHashSet<TResource>(requestEntities, relationships);
4838
_databaseValues = databaseEntities;
4939
_databaseValuesLoaded |= _databaseValues != null;
5040
}
5141

5242
/// <summary>
5343
/// Used internally by the ResourceHookExecutor to make live a bit easier with generics
5444
/// </summary>
55-
internal EntityDiffs(IEnumerable requestEntities,
45+
internal EntityHashSetDiff(IEnumerable requestEntities,
5646
IEnumerable databaseEntities,
5747
Dictionary<RelationshipAttribute, IEnumerable> relationships)
5848
: this((HashSet<TResource>)requestEntities, (HashSet<TResource>)databaseEntities, TypeHelper.ConvertRelationshipDictionary<TResource>(relationships)) { }
5949

6050

6151
/// <inheritdoc />
62-
public IEnumerator<EntityDiffPair<TResource>> GetEnumerator()
52+
public IEnumerator<EntityDiffPair<TResource>> GetDiffs()
6353
{
6454
if (!_databaseValuesLoaded) ThrowNoDbValuesError();
6555

66-
foreach (var entity in Entities)
56+
foreach (var entity in this)
6757
{
68-
TResource currentValueInDatabase = null;
69-
currentValueInDatabase = _databaseValues.Single(e => entity.StringId == e.StringId);
58+
TResource currentValueInDatabase = _databaseValues.Single(e => entity.StringId == e.StringId);
7059
yield return new EntityDiffPair<TResource>(entity, currentValueInDatabase);
7160
}
7261
}
7362

74-
/// <inheritdoc />
75-
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
76-
7763
private HashSet<TResource> ThrowNoDbValuesError()
7864
{
79-
throw new MemberAccessException("Cannot access database entities if the LoadDatabaseValues option is set to false");
65+
throw new MemberAccessException("Cannot iterate over the diffs if the LoadDatabaseValues option is set to false");
8066
}
8167
}
8268

src/JsonApiDotNetCore/Hooks/IResourceHookContainer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public interface IBeforeHooks<TResource> where TResource : class, IIdentifiable
5959
/// multiple entities.
6060
/// <para />
6161
/// The returned <see cref="IEnumerable{TEntity}"/> may be a subset
62-
/// of the <see cref="EntityDiffs{TEntity}.RequestEntities"/> property in parameter <paramref name="entityDiff"/>,
62+
/// of the <see cref="EntityHashSetDiff{TEntity}.RequestEntities"/> property in parameter <paramref name="entityDiff"/>,
6363
/// in which case the operation of the pipeline will not be executed
6464
/// for the omitted entities. The returned set may also contain custom
6565
/// changes of the properties on the entities.
@@ -77,7 +77,7 @@ public interface IBeforeHooks<TResource> where TResource : class, IIdentifiable
7777
/// <returns>The transformed entity set</returns>
7878
/// <param name="entityDiff">The entity diff.</param>
7979
/// <param name="pipeline">An enum indicating from where the hook was triggered.</param>
80-
IEnumerable<TResource> BeforeUpdate(IEntityDiffs<TResource> entityDiff, ResourcePipeline pipeline);
80+
IEnumerable<TResource> BeforeUpdate(IEntityHashSetDiff<TResource> entityDiff, ResourcePipeline pipeline);
8181

8282
/// <summary>
8383
/// Implement this hook to run custom logic in the <see cref=" EntityResourceService{T}"/>

src/JsonApiDotNetCore/Hooks/ResourceHookExecutor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public virtual IEnumerable<TEntity> BeforeUpdate<TEntity>(IEnumerable<TEntity> e
4949
{
5050
var relationships = node.RelationshipsToNextLayer.Select(p => p.Attribute).ToArray();
5151
var dbValues = LoadDbValues(typeof(TEntity), (IEnumerable<TEntity>)node.UniqueEntities, ResourceHook.BeforeUpdate, relationships);
52-
var diff = new EntityDiffs<TEntity>(node.UniqueEntities, dbValues, node.PrincipalsToNextLayer());
52+
var diff = new EntityHashSetDiff<TEntity>(node.UniqueEntities, dbValues, node.PrincipalsToNextLayer());
5353
IEnumerable<TEntity> updated = container.BeforeUpdate(diff, pipeline);
5454
node.UpdateUnique(updated);
5555
node.Reassign(entities);

src/JsonApiDotNetCore/Models/ResourceDefinition.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ public virtual void AfterUpdateRelationship(IRelationshipsDictionary<T> entities
179179
/// <inheritdoc/>
180180
public virtual void BeforeRead(ResourcePipeline pipeline, bool isIncluded = false, string stringId = null) { }
181181
/// <inheritdoc/>
182-
public virtual IEnumerable<T> BeforeUpdate(IEntityDiffs<T> entityDiff, ResourcePipeline pipeline) { return entityDiff.Entities; }
182+
public virtual IEnumerable<T> BeforeUpdate(IEntityHashSetDiff<T> entityDiff, ResourcePipeline pipeline) { return entityDiff.Entities; }
183183
/// <inheritdoc/>
184184
public virtual IEnumerable<T> BeforeDelete(IEntityHashSet<T> entities, ResourcePipeline pipeline) { return entities; }
185185
/// <inheritdoc/>

test/UnitTests/ResourceHooks/AffectedEntitiesHelperTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public void EntityDiff_GetByRelationships()
8787
{
8888
// arrange
8989
var dbEntities = new HashSet<Dummy>(AllEntities.Select(e => new Dummy { Id = e.Id }).ToList());
90-
EntityDiffs<Dummy> diffs = new EntityDiffs<Dummy>(AllEntities, dbEntities, Relationships);
90+
EntityHashSetDiff<Dummy> diffs = new EntityHashSetDiff<Dummy>(AllEntities, dbEntities, Relationships);
9191

9292
// act
9393
Dictionary<RelationshipAttribute, HashSet<Dummy>> toOnes = diffs.Entities.GetByRelationship<ToOne>();
@@ -120,7 +120,7 @@ public void EntityDiff_Loops_Over_Diffs()
120120
{
121121
// arrange
122122
var dbEntities = new HashSet<Dummy>(AllEntities.Select(e => new Dummy { Id = e.Id }));
123-
EntityDiffs<Dummy> diffs = new EntityDiffs<Dummy>(AllEntities, dbEntities, Relationships);
123+
EntityHashSetDiff<Dummy> diffs = new EntityHashSetDiff<Dummy>(AllEntities, dbEntities, Relationships);
124124

125125
// Assert & act
126126
foreach (EntityDiffPair<Dummy> diff in diffs)

test/UnitTests/ResourceHooks/ResourceHookExecutor/Update/BeforeUpdateTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public void BeforeUpdate()
2424
hookExecutor.BeforeUpdate(todoList, ResourcePipeline.Patch);
2525

2626
// assert
27-
todoResourceMock.Verify(rd => rd.BeforeUpdate(It.IsAny<IEntityDiffs<TodoItem>>(), ResourcePipeline.Patch), Times.Once());
27+
todoResourceMock.Verify(rd => rd.BeforeUpdate(It.IsAny<IEntityHashSetDiff<TodoItem>>(), ResourcePipeline.Patch), Times.Once());
2828
ownerResourceMock.Verify(rd => rd.BeforeUpdateRelationship(It.IsAny<HashSet<string>>(), It.IsAny<IRelationshipsDictionary<Person>>(), ResourcePipeline.Patch), Times.Once());
2929
VerifyNoOtherCalls(todoResourceMock, ownerResourceMock);
3030
}
@@ -62,7 +62,7 @@ public void BeforeUpdate_Without_Child_Hook_Implemented()
6262
hookExecutor.BeforeUpdate(todoList, ResourcePipeline.Patch);
6363

6464
// assert
65-
todoResourceMock.Verify(rd => rd.BeforeUpdate(It.IsAny<IEntityDiffs<TodoItem>>(), ResourcePipeline.Patch), Times.Once());
65+
todoResourceMock.Verify(rd => rd.BeforeUpdate(It.IsAny<IEntityHashSetDiff<TodoItem>>(), ResourcePipeline.Patch), Times.Once());
6666
VerifyNoOtherCalls(todoResourceMock, ownerResourceMock);
6767
}
6868

test/UnitTests/ResourceHooks/ResourceHookExecutor/Update/BeforeUpdate_WithDbValues_Tests.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public void BeforeUpdate()
5959
hookExecutor.BeforeUpdate(todoList, ResourcePipeline.Patch);
6060

6161
// assert
62-
todoResourceMock.Verify(rd => rd.BeforeUpdate(It.Is<IEntityDiffs<TodoItem>>((diff) => TodoCheckDiff(diff, description)), ResourcePipeline.Patch), Times.Once());
62+
todoResourceMock.Verify(rd => rd.BeforeUpdate(It.Is<IEntityHashSetDiff<TodoItem>>((diff) => TodoCheckDiff(diff, description)), ResourcePipeline.Patch), Times.Once());
6363
ownerResourceMock.Verify(rd => rd.BeforeUpdateRelationship(
6464
It.Is<HashSet<string>>(ids => PersonIdCheck(ids, personId)),
6565
It.Is<IRelationshipsDictionary<Person>>(rh => PersonCheck(lastName, rh)),
@@ -93,7 +93,7 @@ public void BeforeUpdate_Deleting_Relationship()
9393
hookExecutor.BeforeUpdate(_todoList, ResourcePipeline.Patch);
9494

9595
// assert
96-
todoResourceMock.Verify(rd => rd.BeforeUpdate(It.Is<IEntityDiffs<TodoItem>>((diff) => TodoCheckDiff(diff, description)), ResourcePipeline.Patch), Times.Once());
96+
todoResourceMock.Verify(rd => rd.BeforeUpdate(It.Is<IEntityHashSetDiff<TodoItem>>((diff) => TodoCheckDiff(diff, description)), ResourcePipeline.Patch), Times.Once());
9797
ownerResourceMock.Verify(rd => rd.BeforeImplicitUpdateRelationship(
9898
It.Is<IRelationshipsDictionary<Person>>(rh => PersonCheck(lastName + lastName, rh)),
9999
ResourcePipeline.Patch),
@@ -140,7 +140,7 @@ public void BeforeUpdate_Without_Child_Hook_Implemented()
140140
hookExecutor.BeforeUpdate(todoList, ResourcePipeline.Patch);
141141

142142
// assert
143-
todoResourceMock.Verify(rd => rd.BeforeUpdate(It.Is<IEntityDiffs<TodoItem>>((diff) => TodoCheckDiff(diff, description)), ResourcePipeline.Patch), Times.Once());
143+
todoResourceMock.Verify(rd => rd.BeforeUpdate(It.Is<IEntityHashSetDiff<TodoItem>>((diff) => TodoCheckDiff(diff, description)), ResourcePipeline.Patch), Times.Once());
144144
todoResourceMock.Verify(rd => rd.BeforeImplicitUpdateRelationship(
145145
It.Is<IRelationshipsDictionary<TodoItem>>(rh => TodoCheck(rh, description + description)),
146146
ResourcePipeline.Patch),
@@ -161,7 +161,7 @@ public void BeforeUpdate_NoImplicit()
161161
hookExecutor.BeforeUpdate(todoList, ResourcePipeline.Patch);
162162

163163
// assert
164-
todoResourceMock.Verify(rd => rd.BeforeUpdate(It.Is<IEntityDiffs<TodoItem>>((diff) => TodoCheckDiff(diff, description)), ResourcePipeline.Patch), Times.Once());
164+
todoResourceMock.Verify(rd => rd.BeforeUpdate(It.Is<IEntityHashSetDiff<TodoItem>>((diff) => TodoCheckDiff(diff, description)), ResourcePipeline.Patch), Times.Once());
165165
ownerResourceMock.Verify(rd => rd.BeforeUpdateRelationship(
166166
It.Is<HashSet<string>>(ids => PersonIdCheck(ids, personId)),
167167
It.IsAny<IRelationshipsDictionary<Person>>(),
@@ -204,11 +204,11 @@ public void BeforeUpdate_NoImplicit_Without_Child_Hook_Implemented()
204204
hookExecutor.BeforeUpdate(todoList, ResourcePipeline.Patch);
205205

206206
// assert
207-
todoResourceMock.Verify(rd => rd.BeforeUpdate(It.Is<IEntityDiffs<TodoItem>>((diff) => TodoCheckDiff(diff, description)), ResourcePipeline.Patch), Times.Once());
207+
todoResourceMock.Verify(rd => rd.BeforeUpdate(It.Is<IEntityHashSetDiff<TodoItem>>((diff) => TodoCheckDiff(diff, description)), ResourcePipeline.Patch), Times.Once());
208208
VerifyNoOtherCalls(todoResourceMock, ownerResourceMock);
209209
}
210210

211-
private bool TodoCheckDiff(IEntityDiffs<TodoItem> diff, string checksum)
211+
private bool TodoCheckDiff(IEntityHashSetDiff<TodoItem> diff, string checksum)
212212
{
213213
var diffPair = diff.Single();
214214
var dbCheck = diffPair.DatabaseValue.Description == checksum;

test/UnitTests/ResourceHooks/ResourceHooksTestsSetup.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,8 +260,8 @@ void MockHooks<TModel>(Mock<IResourceHookContainer<TModel>> resourceDefinition)
260260
.Setup(rd => rd.BeforeRead(It.IsAny<ResourcePipeline>(), It.IsAny<bool>(), It.IsAny<string>()))
261261
.Verifiable();
262262
resourceDefinition
263-
.Setup(rd => rd.BeforeUpdate(It.IsAny<IEntityDiffs<TModel>>(), It.IsAny<ResourcePipeline>()))
264-
.Returns<EntityDiffs<TModel>, ResourcePipeline>((entityDiff, context) => entityDiff.Entities)
263+
.Setup(rd => rd.BeforeUpdate(It.IsAny<IEntityHashSetDiff<TModel>>(), It.IsAny<ResourcePipeline>()))
264+
.Returns<EntityHashSetDiff<TModel>, ResourcePipeline>((entityDiff, context) => entityDiff.Entities)
265265
.Verifiable();
266266
resourceDefinition
267267
.Setup(rd => rd.BeforeDelete(It.IsAny<IEntityHashSet<TModel>>(), It.IsAny<ResourcePipeline>()))

0 commit comments

Comments
 (0)