diff --git a/Directory.Packages.props b/Directory.Packages.props
index e37b40b..b546236 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -14,6 +14,7 @@
+
diff --git a/src/CommunityToolkit.Datasync.Client/Offline/OperationsQueue/OperationsQueueManager.cs b/src/CommunityToolkit.Datasync.Client/Offline/OperationsQueue/OperationsQueueManager.cs
index 1a378b7..1c4fab5 100644
--- a/src/CommunityToolkit.Datasync.Client/Offline/OperationsQueue/OperationsQueueManager.cs
+++ b/src/CommunityToolkit.Datasync.Client/Offline/OperationsQueue/OperationsQueueManager.cs
@@ -69,7 +69,7 @@ internal OperationsQueueManager(OfflineDbContext context)
internal List GetChangedEntitiesInScope()
=> ChangeTracker.Entries()
.Where(e => e.State is EntityState.Added or EntityState.Modified or EntityState.Deleted)
- .Where(e => this._entityMap.ContainsKey(e.Entity.GetType().FullName.AsNullableEmptyString()))
+ .Where(e => this._entityMap.ContainsKey(e.Metadata.Name.AsNullableEmptyString()))
.ToList();
///
diff --git a/tests/CommunityToolkit.Datasync.Client.Test/CommunityToolkit.Datasync.Client.Test.csproj b/tests/CommunityToolkit.Datasync.Client.Test/CommunityToolkit.Datasync.Client.Test.csproj
index 51d02db..132f7e0 100644
--- a/tests/CommunityToolkit.Datasync.Client.Test/CommunityToolkit.Datasync.Client.Test.csproj
+++ b/tests/CommunityToolkit.Datasync.Client.Test/CommunityToolkit.Datasync.Client.Test.csproj
@@ -1,6 +1,7 @@
+
diff --git a/tests/CommunityToolkit.Datasync.Client.Test/Offline/Helpers/BaseTest.cs b/tests/CommunityToolkit.Datasync.Client.Test/Offline/Helpers/BaseTest.cs
index 722fdad..1a794f8 100644
--- a/tests/CommunityToolkit.Datasync.Client.Test/Offline/Helpers/BaseTest.cs
+++ b/tests/CommunityToolkit.Datasync.Client.Test/Offline/Helpers/BaseTest.cs
@@ -23,12 +23,13 @@ public abstract class BaseTest
///
/// Creates a version of the TestDbContext backed by SQLite.
///
- protected static TestDbContext CreateContext()
+ protected static TestDbContext CreateContext(Action> configureOptions = null)
{
SqliteConnection connection = new("Data Source=:memory:");
connection.Open();
DbContextOptionsBuilder optionsBuilder = new DbContextOptionsBuilder()
.UseSqlite(connection);
+ configureOptions?.Invoke(optionsBuilder);
TestDbContext context = new(optionsBuilder.Options) { Connection = connection };
// Ensure the database is created.
diff --git a/tests/CommunityToolkit.Datasync.Client.Test/Offline/OperationsQueueManager_Tests.cs b/tests/CommunityToolkit.Datasync.Client.Test/Offline/OperationsQueueManager_Tests.cs
index 3fc9d58..5aa9fb3 100644
--- a/tests/CommunityToolkit.Datasync.Client.Test/Offline/OperationsQueueManager_Tests.cs
+++ b/tests/CommunityToolkit.Datasync.Client.Test/Offline/OperationsQueueManager_Tests.cs
@@ -411,4 +411,76 @@ public void ToOperationKind_Invalid_Throws()
act.Should().Throw();
}
#endregion
+
+ #region LazyLoadingProxies Support
+ [Fact]
+ public async Task LLP_PushAsync_Addition_Works()
+ {
+ TestDbContext llpContext = CreateContext(x => x.UseLazyLoadingProxies());
+ ClientMovie clientMovie = new(TestData.Movies.BlackPanther) { Id = Guid.NewGuid().ToString("N") };
+ string clientMovieJson = DatasyncSerializer.Serialize(clientMovie);
+ llpContext.Movies.Add(clientMovie);
+ llpContext.SaveChanges();
+
+ ClientMovie responseMovie = new(TestData.Movies.BlackPanther) { Id = clientMovie.Id, UpdatedAt = DateTimeOffset.UtcNow, Version = Guid.NewGuid().ToString() };
+ string expectedJson = DatasyncSerializer.Serialize(responseMovie);
+ llpContext.Handler.AddResponseContent(expectedJson, HttpStatusCode.Created);
+
+ PushResult results = await llpContext.QueueManager.PushAsync([typeof(ClientMovie)], new PushOptions());
+ results.IsSuccessful.Should().BeTrue();
+ results.CompletedOperations.Should().Be(1);
+ results.FailedRequests.Should().BeEmpty();
+
+ llpContext.DatasyncOperationsQueue.Should().BeEmpty();
+
+ ClientMovie actualMovie = llpContext.Movies.SingleOrDefault(x => x.Id == clientMovie.Id);
+ actualMovie.UpdatedAt!.Should().BeCloseTo((DateTimeOffset)responseMovie.UpdatedAt, TimeSpan.FromMicroseconds(1000));
+ actualMovie.Version.Should().Be(responseMovie.Version);
+ }
+
+ [Fact]
+ public async Task LLP_PushAsync_Removal_Works()
+ {
+ TestDbContext llpContext = CreateContext(x => x.UseLazyLoadingProxies());
+ ClientMovie clientMovie = new(TestData.Movies.BlackPanther) { Id = Guid.NewGuid().ToString("N") };
+ llpContext.Movies.Add(clientMovie);
+ llpContext.SaveChanges(acceptAllChangesOnSuccess: true, addToQueue: false);
+
+ llpContext.Movies.Remove(clientMovie);
+ llpContext.SaveChanges();
+ llpContext.Handler.AddResponse(HttpStatusCode.NoContent);
+
+ PushResult results = await llpContext.QueueManager.PushAsync([typeof(ClientMovie)], new PushOptions());
+ results.IsSuccessful.Should().BeTrue();
+ results.CompletedOperations.Should().Be(1);
+ results.FailedRequests.Should().BeEmpty();
+
+ llpContext.DatasyncOperationsQueue.Should().BeEmpty();
+ llpContext.Movies.Find(clientMovie.Id).Should().BeNull();
+ }
+
+ [Fact]
+ public async Task LLP_PushAsync_Replacement_Works()
+ {
+ TestDbContext llpContext = CreateContext(x => x.UseLazyLoadingProxies());
+ ClientMovie clientMovie = new(TestData.Movies.BlackPanther) { Id = Guid.NewGuid().ToString("N") };
+ llpContext.Movies.Add(clientMovie);
+ llpContext.SaveChanges(acceptAllChangesOnSuccess: true, addToQueue: false);
+
+ clientMovie.Title = "Foo";
+ llpContext.Update(clientMovie);
+ llpContext.SaveChanges();
+
+ ClientMovie responseMovie = new(TestData.Movies.BlackPanther) { Id = clientMovie.Id, UpdatedAt = DateTimeOffset.UtcNow, Version = Guid.NewGuid().ToString() };
+ string expectedJson = DatasyncSerializer.Serialize(responseMovie);
+ llpContext.Handler.AddResponseContent(expectedJson, HttpStatusCode.OK);
+
+ PushResult results = await llpContext.QueueManager.PushAsync([typeof(ClientMovie)], new PushOptions());
+ results.IsSuccessful.Should().BeTrue();
+ results.CompletedOperations.Should().Be(1);
+ results.FailedRequests.Should().BeEmpty();
+
+ llpContext.DatasyncOperationsQueue.Should().BeEmpty();
+ }
+ #endregion
}