• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lucaslorentz / auto-compute / 18246144053

04 Oct 2025 03:25PM UTC coverage: 83.552% (-0.02%) from 83.569%
18246144053

push

github

lucaslorentz
Refactor entity context propagation

83 of 90 new or added lines in 18 files covered. (92.22%)

1849 of 2213 relevant lines covered (83.55%)

865.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.74
/src/LLL.AutoCompute/EntityContexts/EntityContext.cs
1
using System.Linq.Expressions;
2

3
namespace LLL.AutoCompute.EntityContexts;
4

5
public abstract class EntityContext(Expression expression)
842✔
6
{
7
    private readonly HashSet<IObservedMember> _observedMembers = [];
842✔
8
    private readonly IList<EntityContext> _childContexts = [];
842✔
9

10
    public IReadOnlySet<IObservedMember> ObservedMembers => _observedMembers;
80✔
11
    public IEnumerable<EntityContext> ChildContexts => _childContexts;
×
12

13
    public abstract IObservedEntityType EntityType { get; }
14
    public abstract bool IsTrackingChanges { get; }
15
    public Guid Id { get; } = Guid.NewGuid();
842✔
NEW
16
    public Expression Expression => expression;
×
17

18
    public void RegisterObservedMember(IObservedMember member)
19
    {
20
        _observedMembers.Add(member);
448✔
21
    }
22

23
    public IEnumerable<IObservedMember> GetAllObservedMembers()
24
    {
25
        foreach (var om in _observedMembers)
10,364✔
26
            yield return om;
1,752✔
27

28
        foreach (var cc in _childContexts)
8,430✔
29
        {
30
            foreach (var om in cc.GetAllObservedMembers())
6,344✔
31
            {
32
                yield return om;
1,722✔
33
            }
34
        }
35
    }
36

37
    public virtual void RegisterChildContext(EntityContext context)
38
    {
39
        _childContexts.Add(context);
422✔
40
    }
41

42
    public async Task<IReadOnlyCollection<object>> GetAffectedEntitiesAsync(object input, IncrementalContext incrementalContext)
43
    {
44
        var entities = new HashSet<object>();
5,090✔
45

46
        foreach (var member in _observedMembers)
17,900✔
47
        {
48
            if (member is IObservedProperty observedProperty)
3,860✔
49
            {
50
                var propertyChanges = await observedProperty.GetChangesAsync(input);
2,628✔
51
                foreach (var ent in propertyChanges.GetEntityChanges())
11,860✔
52
                {
53
                    if (!EntityType.IsInstanceOfType(ent))
3,302✔
54
                        continue;
55

56
                    entities.Add(ent);
3,302✔
57
                }
58
            }
59
            else if (member is IObservedNavigation observedNavigation)
1,232✔
60
            {
61
                var navigationChanges = await observedNavigation.GetChangesAsync(input);
1,232✔
62
                foreach (var (entity, changes) in navigationChanges.GetEntityChanges())
4,560✔
63
                {
64
                    if (!EntityType.IsInstanceOfType(entity))
1,048✔
65
                        continue;
66

67
                    entities.Add(entity);
1,048✔
68
                    foreach (var addedEntity in changes.Added)
4,004✔
69
                    {
70
                        incrementalContext.SetShouldLoadAll(addedEntity);
954✔
71
                        incrementalContext.AddCurrentEntity(entity, observedNavigation, addedEntity);
954✔
72
                    }
73
                    foreach (var removedEntity in changes.Removed)
2,304✔
74
                    {
75
                        incrementalContext.SetShouldLoadAll(removedEntity);
104✔
76
                        incrementalContext.AddOriginalEntity(entity, observedNavigation, removedEntity);
104✔
77
                    }
78
                }
79
            }
80
        }
81

82
        foreach (var childContext in _childContexts)
16,784✔
83
        {
84
            var ents = await childContext.GetParentAffectedEntities(input, incrementalContext);
3,302✔
85
            foreach (var ent in ents)
10,464✔
86
            {
87
                if (!EntityType.IsInstanceOfType(ent))
1,930✔
88
                    continue;
89

90
                entities.Add(ent);
1,930✔
91
            }
92
        }
93

94
        return entities;
5,090✔
95
    }
96

97
    public abstract Task<IReadOnlyCollection<object>> GetParentAffectedEntities(object input, IncrementalContext incrementalContext);
98

99
    public virtual async Task EnrichIncrementalContextAsync(object input, IReadOnlyCollection<object> entities, IncrementalContext incrementalContext)
100
    {
101
        foreach (var childContext in _childContexts)
2,840✔
102
            await childContext.EnrichIncrementalContextFromParentAsync(input, entities, incrementalContext);
618✔
103
    }
104

105
    public virtual async Task EnrichIncrementalContextFromParentAsync(object input, IReadOnlyCollection<object> parentEntities, IncrementalContext incrementalContext)
106
    {
107
        await EnrichIncrementalContextAsync(input, parentEntities, incrementalContext);
358✔
108
    }
109

110
    public abstract Task EnrichIncrementalContextTowardsRootAsync(object input, IReadOnlyCollection<object> entities, IncrementalContext incrementalContext);
111

112
    public virtual async Task PreLoadNavigationsAsync(object input, IReadOnlyCollection<object> entities)
113
    {
114
        foreach (var childContext in _childContexts)
19,000✔
115
            await childContext.PreLoadNavigationsFromParentAsync(input, entities);
2,700✔
116
    }
117

118
    public virtual async Task PreLoadNavigationsFromParentAsync(object input, IReadOnlyCollection<object> parentEntities)
119
    {
120
        await PreLoadNavigationsAsync(input, parentEntities);
1,416✔
121
    }
122

123
    public abstract void MarkNavigationToLoadAll();
124

125
    public void ValidateAll()
126
    {
127
        ValidateSelf();
878✔
128

129
        foreach (var childContext in _childContexts)
2,616✔
130
            childContext.ValidateAll();
430✔
131
    }
132

133
    public virtual void ValidateSelf() { }
134
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc