Skip to content

Change IEntityDiff<T> to IDiffableEntityHashSet<T> #538

Closed
@maurei

Description

@maurei

I would like to propose to change IEntityDiff<T> to IDiffableEntityHashSet<T> which introduces a change in behaviour that I believe is more intuitive. We can still come up with a better name, but the meat of this proposal is the change of behaviour, as discussed below.

Why?
Because I think the current behaviour of IEntityDiff<T> is not very intuitive. Let's explore this by comparing the BeforeUpdate hook, where the diff is used, with the BeforeCreate hook, where the more intuitive IEntityHashSet<T> is used. We want them to behave more or less the same, but IEntityDiff<T> deviates from IEntityHashSet<T> in a non-intuitive way.

The solution is then to replace IEntityDiff<T> with IDiffableEntityHashSet<T> so that the behaviour is similar again.

BeforeCreate
In the BeforeCreate hook we have a IEntityHashSet<T>, which is basically just a hashset with some extra helpermethods that relate to affected relationships.

// intuitive: the IEntityHashSet parameter is just a HashSet of entities which the hook is fired
public override IEnumerable<Tag> BeforeCreate(IEntityHashSet<Tag> entities, ResourcePipeline pipeline)
{
    // which means we can loop over entities:
    foreach (Tag tag in entities)
    {
        // do something with tag
    }

    // But IEntityHashSet not just a HashSet: its a hashset PLUS some 
    // helpermethods to access information about affected relationships to other models.
    var tagsAssignedToArticles = entities.GetByRelationship<Article>();
    var tagsAssignedToBlogs = entities.GetByRelationship<Blog>();

    // lastly, we can return a filtered list of the affected tags by just using 
    // LINQ on our IEntityHashSet, because IEntityHashSet is basically just a HashSet.
    return entities.Where( e => SomeCondition(e));
}

From the comments in the above example it should be clear why IEntityHashSet<T> is more or less just a HashSet<T>.

BeforeUpdate currently
Let's now compare IEntityDiff<T> as used in BeforeUpdate with IEntityHashSet<T>. It does not behave the same:

// I think it would be intuitive if, like with BeforeCreate, let the IEntityDiffs<Tag> 
// just be a hashset of affected entities PLUS relationship helpermethods and now also
// PLUS some helper methods related to diffs. But it is not. The example below shows 
// how it is different from this behaviour
public override IEnumerable<Tag> BeforeUpdate(IEntityDiffs<Tag> entityDiff, ResourcePipeline pipeline)
{
    // we loop over DiffPairs, not the affected tags.
    // so IEntityDiffs behaves like a collection of EntityDiffPairs<T>, not a collection of T
    foreach (EntityDiffPair<Tag> element in entityDiff)
    {
        var entityFromRequestBody = element.Entity;
        var entityFromDatabase = element.DatabaseValue;
    }
	
	// the return type of the hook, however, is still IEnumerable<T>. 
	// so we need to get that collection by accessing it manually like below, and return that
    return entityDiff.Entities;
}

From the above examples it should be clear that IEntityHashSet<T> behaves like a collection of T, whereas IEntityDiff<T> does not. The current proposal is to change IEntityDiff<T> to IEntityHashSetDiff<T> so that it does.

BeforeUpdate proposed
The before update hook will then look like this:

// Now IDiffableEntityHashSet <Tag> behaves just like a collection of tags again
public override IEnumerable<Tag> BeforeUpdate(IDiffableEntityHashSet<Tag> entities, ResourcePipeline pipeline)
{
    // Now we're looping over tags again: the affected entities from the request
    foreach (Tag element in entities)
    {
        // do something with tag
    }

    // we can still loop over the DiffPairs to check out the current database value
    // of each affected entity in the request
    foreach (EntityDiffPair<Tag> element in entities.GetDiffs())
    {
        var entityFromRequestBody = element.Entity;
        var entityFromDatabase = element.DatabaseValue;
    }

    // we can just return the list of affected entities again (or a filtered version of that)
    return entities.Where(e => SomeCondition(e));
}

In conclusion
Where IEntityHashSet<T> is just a HashSet<T> with some helper methods for accessing relationships, IDiffableEntityHashSet<T> will be just a IEntityHashSet<T> with yet another helper method:GetDiffs(), which gives the ability to loop over diffed values of affected entities.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions