ItCompiles.Data.Tracked
0.1.0-preview
Prefix Reserved
dotnet add package ItCompiles.Data.Tracked --version 0.1.0-preview
NuGet\Install-Package ItCompiles.Data.Tracked -Version 0.1.0-preview
<PackageReference Include="ItCompiles.Data.Tracked" Version="0.1.0-preview" />
<PackageVersion Include="ItCompiles.Data.Tracked" Version="0.1.0-preview" />
<PackageReference Include="ItCompiles.Data.Tracked" />
paket add ItCompiles.Data.Tracked --version 0.1.0-preview
#r "nuget: ItCompiles.Data.Tracked, 0.1.0-preview"
#:package ItCompiles.Data.Tracked@0.1.0-preview
#addin nuget:?package=ItCompiles.Data.Tracked&version=0.1.0-preview&prerelease
#tool nuget:?package=ItCompiles.Data.Tracked&version=0.1.0-preview&prerelease
A Lightweight change tracking library for .NET objects and DTOs.
ItCompiles.Data.ChangeTracking allows you to edit complex object graphs without modifying the original data until you're ready. It supports nested objects, collections, commit/rollback, and lazy initialization while remaining fast enough for UI frameworks like Blazor.
Why?
Many applications need an "edit mode" where users can make changes before saving.
Instead of copying entire objects or manually tracking every field, this library wraps your existing DTOs and tracks modifications seperately
The original object is never modified until Commit() is called.
Features
- Track simple properties
- Track nested objects
- Track collections
- Commit or rollback changes
- Lazy object graph creation
- Reflection metadata caching
- Preserve original object references
- Designed for DTO editing
Usage/Examples
Create a tracked object.
var tracked = TrackedBuilder.Build(product);
Access a property (Edit Value).
tracked
.Property(x => x.Name)
.Value;
Access a property (Raw DTO).
tracked.Value
Edit a property.
tracked
.Property(x => x.Name)
.SetValue("New Name");
Check if anything changed.
if (tracked.IsChanged)
{
...
}
Commit changes.
tracked.Commit();
Rollback changes.
tracked.Rollback();
Tracking Nested Objects
Nested objects are tracked automatically.
tracked
.Object(x => x.Customer)
.Property(x => x.Name)
.SetValue("John");
Changes propagate to the parent.
tracked.IsChanged
returns
true
Tracking Collections
Collections support editing without modifying the original collection.
var tags =
tracked.Collection(x => x.Tags);
Replace the collection.
tags.SetCollection(newTags);
Add items.
tags.Add(tag);
Remove items.
tags.Remove(tag);
Clear.
tags.Clear();
Access tracked items.
foreach (var item in tags.Items)
{
item.Property(x => x.Name).SetValue("Updated");
}
Commit
Nothing is written back to the original object until Commit.
tracked.Commit();
Property values are copied back to the original DTO.
Nested objects are committed recursively.
Collections are committed recursively.
Rollback
Discard every pending edit.
tracked.Rollback();
All edited values return to their original state.
Lazy Initialization
Objects and collections are created only when accessed.
This keeps startup costs low for large object graphs.
For example:
tracked.Property(x => x.Name)
does not initialize every collection on the object.
Collections are initialized only when requested.
tracked.Collection(x => x.Tags)
Performance Tips
ItCompiles.Data.Tracked is designed around the idea that most application code reads data far more often than it edits data.
For the best performance, follow these guidelines:
Use the original object for read-only UI
When displaying data (tables, lists, dashboards, reports, etc.), read directly from the wrapped object.
tracked.Value.Name
tracked.Value.Quantity
tracked.Value.Tags.Count
This avoids initializing the change tracker for properties that are never edited.
Use tracked properties only while editing
When entering an edit mode, access the tracked property.
tracked.Property(x => x.Name).Value
tracked.Property(x => x.Name).SetValue("New Name")
This initializes tracking only for the values being edited.
Example
For a data table, prefer:
@tracked.Value.Name
instead of:
@tracked.Property(x => x.Name).Value
The first simply reads the underlying DTO.
The second initializes and accesses the change tracker, which is unnecessary if the value is only being displayed.
Why?
The library uses lazy initialization to avoid creating tracking objects until they are actually needed.
Accessing a tracked property may create tracking metadata for that object, while reading from Value simply accesses the original DTO.
This design keeps rendering extremely fast in UI frameworks such as Blazor, where components may render many times in response to user interaction.
Recommended workflow
- Display data using
tracked.Value. - Enter edit mode only when the user begins editing.
- Read and modify values through
Property(),Object(), andCollection()while editing. - Call
Commit()to apply changes to the original object, orRollback()to discard them.
Following this pattern provides the best balance between performance and change tracking, especially for large object graphs and data-heavy user interfaces.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.0-preview | 120 | 8/10/2026 |