Skip to content

Commit 50fde6d

Browse files
authored
Merge pull request #53 from TrackableEntities/feature/net10-efcore10-upgrade
Upgrade to .NET 10 and EF Core 10
2 parents 098b665 + a1a0de8 commit 50fde6d

7 files changed

Lines changed: 33 additions & 20 deletions

File tree

.github/workflows/deploy.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ jobs:
77
runs-on: ubuntu-latest
88
strategy:
99
matrix:
10-
dotnet-version: [9.x]
10+
dotnet-version: [10.x]
1111
services:
1212
mssql:
1313
image: mcr.microsoft.com/mssql/server:2019-latest

Directory.Build.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project>
22
<PropertyGroup>
3-
<TargetFramework>net9.0</TargetFramework>
3+
<TargetFramework>net10.0</TargetFramework>
44
<Authors>Tony Sneed</Authors>
55
<Company>Tony Sneed</Company>
66
<NoWarn>$(NoWarn);CS1591</NoWarn>
@@ -12,7 +12,7 @@
1212
<GenerateDocumentationFile>True</GenerateDocumentationFile>
1313
<PackageReadmeFile>README.md</PackageReadmeFile>
1414
<PackageReleaseNotes>
15-
https://github.com/TrackableEntities/TrackableEntities.Core/releases/tag/v9.0.0
15+
https://github.com/TrackableEntities/TrackableEntities.Core/releases/tag/v10.0.0
1616
</PackageReleaseNotes>
1717
</PropertyGroup>
1818

README.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Change-tracking across service boundaries with [ASP.NET Core](https://docs.micro
1212

1313
## Installation
1414

15-
Trackable Entities for EF Core 9 is available as a NuGet package that can be installed in an ASP.NET Core Web API project that uses Entity Framework Core.
15+
Trackable Entities for EF Core 10 is available as a NuGet package that can be installed in an ASP.NET Core Web API project that uses Entity Framework Core.
1616

1717
You can use the [Package Manager UI or Console](https://docs.microsoft.com/en-us/nuget/tools/package-manager-console) in Visual Studio to install the TE package.
1818

@@ -28,7 +28,17 @@ dotnet add package TrackableEntities.EF.Core
2828

2929
## Packages for Previous Versions of EntityFramework Core
3030

31-
##### [EntityFramework Core v8](https://www.nuget.org/packages/TrackableEntities.EF.Core/8.0.0) | [EntityFramework Core v7](https://www.nuget.org/packages/TrackableEntities.EF.Core/7.0.0) | [EntityFramework Core v6](https://www.nuget.org/packages/TrackableEntities.EF.Core/6.0.0) | [EntityFramework Core v5](https://www.nuget.org/packages/TrackableEntities.EF.Core/5.0.1) | [EntityFramework Core v3](https://www.nuget.org/packages/TrackableEntities.EF.Core/3.1.1)
31+
##### [EntityFramework Core v9](https://www.nuget.org/packages/TrackableEntities.EF.Core/9.0.1) | [EntityFramework Core v8](https://www.nuget.org/packages/TrackableEntities.EF.Core/8.0.0) | [EntityFramework Core v7](https://www.nuget.org/packages/TrackableEntities.EF.Core/7.0.0) | [EntityFramework Core v6](https://www.nuget.org/packages/TrackableEntities.EF.Core/6.0.0) | [EntityFramework Core v5](https://www.nuget.org/packages/TrackableEntities.EF.Core/5.0.1) | [EntityFramework Core v3](https://www.nuget.org/packages/TrackableEntities.EF.Core/3.1.1)
32+
33+
## EF Core 10 Behavior Changes
34+
35+
EF Core 10 includes a change in entity state validation that affects how Trackable Entities handles certain edge cases:
36+
37+
- **Deleted parent with Added children**: In EF Core 9 and earlier, attempting to delete an entity that had children marked as `Added` would throw an `InvalidOperationException`. EF Core 10 relaxes this validation and allows the operation to proceed.
38+
39+
- **Impact**: If you previously relied on receiving an exception when accidentally marking a parent as `Deleted` while its children were marked as `Added`, this validation is no longer enforced by EF Core. The operation will now proceed, and the child entities will be set to `Deleted` along with their parent.
40+
41+
- **Recommendation**: Ensure your client-side logic properly validates entity state combinations before sending object graphs to the server. Avoid marking parent entities as `Deleted` when child entities are marked as `Added`, as this represents a logical contradiction (you cannot delete a parent while simultaneously adding new children to it).
3242

3343

3444
## Trackable Entities Interfaces

TrackableEntities.EF.Core.Tests/NorthwindDbContextTests.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -850,13 +850,24 @@ public void Apply_Changes_Should_Mark_Unchanged_Order_Deleted_Customer_With_Addr
850850
Customer = order.Customer
851851
};
852852
order.Customer.CustomerAddresses = new List<CustomerAddress> { address1, address2 };
853+
address1.TrackingState = TrackingState.Added;
854+
address2.TrackingState = TrackingState.Added;
853855
order.Customer.TrackingState = TrackingState.Deleted;
854856

855-
// Act / Assert
856-
Exception ex = Assert.Throws<InvalidOperationException>(() => context.ApplyChanges(order));
857+
// Act
858+
// Note: When navigating from Order (many side) to Customer (one side), the Customer's
859+
// Deleted state is overridden to Unchanged since the Customer may be related to other entities.
860+
// However, the Customer's TrackingState property is still Deleted, so when processing
861+
// child entities (CustomerAddresses), they are set to Deleted based on the parent's TrackingState.
862+
context.ApplyChanges(order);
857863

858864
// Assert
859-
Assert.Equal(Constants.ExceptionMessages.DeletedWithAddedChildren, ex.Message);
865+
Assert.Equal(EntityState.Unchanged, context.Entry(order).State);
866+
// Customer is set to Unchanged because it's reached via OneToMany navigation from Order
867+
Assert.Equal(EntityState.Unchanged, context.Entry(order.Customer).State);
868+
// Addresses are set to Deleted because parent's TrackingState is Deleted (even though parent EntityState is Unchanged)
869+
Assert.Equal(EntityState.Deleted, context.Entry(address1).State);
870+
Assert.Equal(EntityState.Deleted, context.Entry(address2).State);
860871
}
861872

862873
[Fact]

TrackableEntities.EF.Core.Tests/TrackableEntities.EF.Core.Tests.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
</PropertyGroup>
66

77
<ItemGroup>
8-
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.0" />
9-
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0" />
8+
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.0" />
9+
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.0" />
1010
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
1111
<PackageReference Include="xunit" Version="2.4.2" />
1212
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">

TrackableEntities.EF.Core/DbContextExtensions.cs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,7 @@ public static void ApplyChanges(this DbContext context, ITrackable item)
6666
if (node.SourceEntry.State == EntityState.Deleted
6767
|| parent?.TrackingState == TrackingState.Deleted)
6868
{
69-
try
70-
{
71-
// Will throw if there are added children
72-
SetEntityState(node.Entry, TrackingState.Deleted.ToEntityState(), trackable);
73-
}
74-
catch (InvalidOperationException e)
75-
{
76-
throw new InvalidOperationException(Constants.ExceptionMessages.DeletedWithAddedChildren, e);
77-
}
69+
SetEntityState(node.Entry, TrackingState.Deleted.ToEntityState(), trackable);
7870
return;
7971
}
8072
break;

TrackableEntities.EF.Core/TrackableEntities.EF.Core.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
</PropertyGroup>
99

1010
<ItemGroup>
11-
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
11+
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.0" />
1212
</ItemGroup>
1313

1414
<ItemGroup>

0 commit comments

Comments
 (0)