Skip to content

Fixed re-grouping on foreign key change, in Join operators #1012

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 101 additions & 1 deletion src/DynamicData.Tests/Cache/InnerJoinFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,59 @@ public void Dispose()
_result?.Dispose();
}

[Fact]
public void RefreshRightKey()
{
_left.Edit(
innerCache =>
{
innerCache.AddOrUpdate(new Device("Device1"));
innerCache.AddOrUpdate(new Device("Device2"));
innerCache.AddOrUpdate(new Device("Device3"));
});

_right.Edit(
innerCache =>
{
innerCache.AddOrUpdate(new DeviceMetaData(1,"Device1"));
innerCache.AddOrUpdate(new DeviceMetaData(2,"Device2"));
innerCache.AddOrUpdate(new DeviceMetaData(3,"Device3"));
});

var refreshItem = _right.Lookup(2).Value;


// Change pairing
refreshItem.Name = "Device3";
_right.Refresh(refreshItem);

_result.Data.Count.Should().Be(3);
_result.Data.Keys.Should().Contain(("Device3", 2));


// Remove pairing
refreshItem.Name = "Device4";
_right.Refresh(refreshItem);

_result.Data.Count.Should().Be(2);
_result.Data.Keys.Should().NotContain(pair => pair.rightKey == 2);


// Restore pairing
refreshItem.Name = "Device2";
_right.Refresh(refreshItem);

_result.Data.Count.Should().Be(3);
_result.Data.Keys.Should().Contain(("Device2", 2));


// No change
_right.Refresh(refreshItem);

_result.Data.Count.Should().Be(3);
_result.Data.Keys.Should().Contain(("Device2", 2));
}

[Fact]
public void RemoveVarious()
{
Expand Down Expand Up @@ -159,6 +212,53 @@ public void UpdateRight()
_result.Data.Count.Should().Be(3);
}

[Fact]
public void UpdateRightKey()
{
_left.Edit(
innerCache =>
{
innerCache.AddOrUpdate(new Device("Device1"));
innerCache.AddOrUpdate(new Device("Device2"));
innerCache.AddOrUpdate(new Device("Device3"));
});

_right.Edit(
innerCache =>
{
innerCache.AddOrUpdate(new DeviceMetaData(1,"Device1"));
innerCache.AddOrUpdate(new DeviceMetaData(2,"Device2"));
innerCache.AddOrUpdate(new DeviceMetaData(3,"Device3"));
});


// Change pairing
_right.AddOrUpdate(new DeviceMetaData(2,"Device3"));

_result.Data.Count.Should().Be(3);
_result.Data.Keys.Should().Contain(("Device3", 2));


// Remove pairing
_right.AddOrUpdate(new DeviceMetaData(2,"Device4"));

_result.Data.Count.Should().Be(2);
_result.Data.Keys.Should().NotContain(pair => pair.rightKey == 2);


// Restore pairing
_right.AddOrUpdate(new DeviceMetaData(2,"Device2"));

_result.Data.Count.Should().Be(3);
_result.Data.Keys.Should().Contain(("Device2", 2));


// No change
_right.AddOrUpdate(new DeviceMetaData(2,"Device2"));

_result.Data.Count.Should().Be(3);
_result.Data.Keys.Should().Contain(("Device2", 2));
}

[Fact]
public void MultipleRight()
Expand Down Expand Up @@ -284,7 +384,7 @@ public class DeviceMetaData(int key, string name, bool isAutoConnect = false) :
{
public bool IsAutoConnect { get; } = isAutoConnect;
public int Key { get; } = key;
public string Name { get; } = name;
public string Name { get; set; } = name;

public override string ToString() => $"Key: {Key}. Metadata: {Name}. IsAutoConnect = {IsAutoConnect}";

Expand Down
87 changes: 87 additions & 0 deletions src/DynamicData.Tests/Cache/InnerJoinManyFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,52 @@ public void Dispose()
_result.Dispose();
}

[Fact]
public void RefreshRightKey()
{
_people.Edit(
innerCache =>
{
innerCache.AddOrUpdate(new Person() { Name = "Person #1", ParentName = string.Empty } );
innerCache.AddOrUpdate(new Person() { Name = "Person #2", ParentName = "Person #1" } );
innerCache.AddOrUpdate(new Person() { Name = "Person #3", ParentName = "Person #2" } );
});

var refreshPerson = _people.Lookup("Person #2").Value;


// Change pairing
refreshPerson.ParentName = "Person #3";
_people.Refresh(refreshPerson);

_result.Data.Count.Should().Be(2);
_result.Data.Items.SelectMany(family => family.Children.Select(child => (family.Parent.Name, child.Name))).Should().NotContain(("Person #1", "Person #2"));
_result.Data.Items.SelectMany(family => family.Children.Select(child => (family.Parent.Name, child.Name))).Should().Contain(("Person #3", "Person #2"));


// Remove pairing
refreshPerson.ParentName = "Person #4";
_people.Refresh(refreshPerson);

_result.Data.Count.Should().Be(1);
_result.Data.Items.SelectMany(family => family.Children.Select(child => (parentName: family.Parent.Name, chilldName: child.Name))).Should().NotContain(pair => pair.chilldName == "Person #2");


// Restore pairing
refreshPerson.ParentName = "Person #1";
_people.Refresh(refreshPerson);

_result.Data.Count.Should().Be(2);
_result.Data.Items.SelectMany(family => family.Children.Select(child => (family.Parent.Name, child.Name))).Should().Contain(("Person #1", "Person #2"));


// No change
_people.Refresh(refreshPerson);

_result.Data.Count.Should().Be(2);
_result.Data.Items.SelectMany(family => family.Children.Select(child => (family.Parent.Name, child.Name))).Should().Contain(("Person #1", "Person #2"));
}

[Fact]
public void RemoveChild()
{
Expand Down Expand Up @@ -136,6 +182,47 @@ public void UpdateParent()
AssertDataIsCorrectlyFormed(updatedPeople);
}

[Fact]
public void UpdateRightKey()
{
_people.Edit(
innerCache =>
{
innerCache.AddOrUpdate(new Person() { Name = "Person #1", ParentName = string.Empty } );
innerCache.AddOrUpdate(new Person() { Name = "Person #2", ParentName = "Person #1" } );
innerCache.AddOrUpdate(new Person() { Name = "Person #3", ParentName = "Person #2" } );
});


// Change pairing
_people.AddOrUpdate(new Person() { Name = "Person #2", ParentName = "Person #3" });

_result.Data.Count.Should().Be(2);
_result.Data.Items.SelectMany(family => family.Children.Select(child => (family.Parent.Name, child.Name))).Should().NotContain(("Person #1", "Person #2"));
_result.Data.Items.SelectMany(family => family.Children.Select(child => (family.Parent.Name, child.Name))).Should().Contain(("Person #3", "Person #2"));


// Remove pairing
_people.AddOrUpdate(new Person() { Name = "Person #2", ParentName = "Person #4" });

_result.Data.Count.Should().Be(1);
_result.Data.Items.SelectMany(family => family.Children.Select(child => (parentName: family.Parent.Name, chilldName: child.Name))).Should().NotContain(pair => pair.chilldName == "Person #2");


// Restore pairing
_people.AddOrUpdate(new Person() { Name = "Person #2", ParentName = "Person #1" });

_result.Data.Count.Should().Be(2);
_result.Data.Items.SelectMany(family => family.Children.Select(child => (family.Parent.Name, child.Name))).Should().Contain(("Person #1", "Person #2"));


// No change
_people.AddOrUpdate(new Person() { Name = "Person #2", ParentName = "Person #1" });

_result.Data.Count.Should().Be(2);
_result.Data.Items.SelectMany(family => family.Children.Select(child => (family.Parent.Name, child.Name))).Should().Contain(("Person #1", "Person #2"));
}

private void AssertDataIsCorrectlyFormed(Person[] allPeople, params string[] missingParents)
{
var grouped = allPeople.GroupBy(p => p.ParentName).Where(p => p.Any() && !missingParents.Contains(p.Key)).AsArray();
Expand Down
Loading
Loading