Skip to content

Commit 67266b1

Browse files
author
fabien.menager
committed
Merge branch 'master' into fix/concat-iterator-perf
2 parents c6b323e + 8fefaef commit 67266b1

55 files changed

Lines changed: 2029 additions & 323 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/build.yml

Lines changed: 22 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ on:
55
release:
66
types:
77
- published
8-
8+
99
env:
1010
# Stop wasting time caching packages
1111
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
@@ -15,42 +15,33 @@ env:
1515
GITHUB_FEED: https://nuget.pkg.github.com/koenbeuk/
1616
GITHUB_USER: koenbeuk
1717
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
18-
18+
1919
jobs:
2020
build:
2121
strategy:
2222
matrix:
2323
os: [ubuntu-latest, windows-latest, macos-latest]
24-
version: [1, 2, 3]
25-
include:
26-
- version: 1
27-
configuration: ReleaseV1
28-
- version: 2
29-
configuration: ReleaseV2
30-
- version: 3
31-
configuration: Release
32-
runs-on: ${{ matrix.os }}
24+
runs-on: ${{ matrix.os }}
3325

3426
steps:
35-
- uses: actions/checkout@v2
27+
- uses: actions/checkout@v4
3628
- name: Setup .NET Core
37-
uses: actions/setup-dotnet@v1
29+
uses: actions/setup-dotnet@v4
3830
with:
39-
dotnet-version: 6.0.x
40-
include-prerelease: True
31+
global-json-file: global.json
4132
- name: Install dependencies
42-
run: dotnet restore EntityFrameworkCore.Triggered.sln -p:Configuration=${{ matrix.configuration }}
33+
run: dotnet restore EntityFrameworkCore.Triggered.sln -p:Configuration=Release
4334
- name: Build
44-
run: dotnet build --configuration ${{ matrix.configuration }} --no-restore EntityFrameworkCore.Triggered.sln
35+
run: dotnet build --configuration Release --no-restore EntityFrameworkCore.Triggered.sln
4536
- name: Test
46-
run: dotnet test --configuration ${{ matrix.configuration }} --verbosity normal EntityFrameworkCore.Triggered.sln
37+
run: dotnet test --configuration Release --verbosity normal EntityFrameworkCore.Triggered.sln
4738
- name: Pack
4839
if: matrix.os == 'ubuntu-latest'
49-
run: |
50-
dotnet pack -v normal --configuration ${{ matrix.configuration }} --include-symbols --include-source -p:PackageVersion=${{ matrix.version }}-pre-$GITHUB_RUN_ID -o nupkg EntityFrameworkCore.Triggered.Core.slnf
40+
run: |
41+
dotnet pack -v normal --configuration Release --include-symbols --include-source -p:PackageVersion=3-pre-$GITHUB_RUN_ID -o nupkg EntityFrameworkCore.Triggered.Core.slnf
5142
- name: Upload Artifact
5243
if: matrix.os == 'ubuntu-latest'
53-
uses: actions/upload-artifact@v2
44+
uses: actions/upload-artifact@v4
5445
with:
5546
name: nupkg
5647
path: ./nupkg/*.nupkg
@@ -59,32 +50,32 @@ jobs:
5950
strategy:
6051
matrix:
6152
os: [ubuntu-latest, windows-latest, macos-latest]
62-
runs-on: ${{ matrix.os }}
63-
53+
runs-on: ${{ matrix.os }}
54+
6455
steps:
65-
- uses: actions/checkout@v2
56+
- uses: actions/checkout@v4
6657
- name: Setup .NET Core
67-
uses: actions/setup-dotnet@v1
58+
uses: actions/setup-dotnet@v4
6859
with:
69-
dotnet-version: 6.0.x
70-
include-prerelease: True
60+
global-json-file: global.json
7161
- name: Install dependencies
7262
run: dotnet restore EntityFrameworkCore.Triggered.Samples.slnf
7363
- name: Build
74-
run: dotnet build --configuration Release --no-restore EntityFrameworkCore.Triggered.Samples.slnf
75-
64+
run: dotnet build --configuration Release --no-restore EntityFrameworkCore.Triggered.Samples.slnf
65+
7666
prerelease:
7767
needs: build
7868
if: github.ref == 'refs/heads/master'
7969
runs-on: ubuntu-latest
8070
steps:
8171
- name: Download Artifact
82-
uses: actions/download-artifact@v1
72+
uses: actions/download-artifact@v4
8373
with:
8474
name: nupkg
75+
path: nupkg
8576
- name: Push to GitHub Feed
8677
run: |
8778
for f in ./nupkg/*.nupkg
8879
do
8980
dotnet nuget push $f --source $GITHUB_FEED --api-key ${{github.token}} --skip-duplicate --no-symbols
90-
done
81+
done

.github/workflows/release.yml

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ on:
33
release:
44
types:
55
- published
6-
6+
77
env:
88
# Stop wasting time caching packages
99
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
@@ -16,27 +16,24 @@ env:
1616
# Official NuGet Feed settings
1717
NUGET_FEED: https://api.nuget.org/v3/index.json
1818
NUGET_KEY: ${{ secrets.NUGET_KEY }}
19-
19+
2020
jobs:
2121
deploy:
2222
runs-on: ubuntu-latest
2323
steps:
24-
- uses: actions/checkout@v2
24+
- uses: actions/checkout@v4
2525
- name: Setup .NET Core
26-
uses: actions/setup-dotnet@v1
26+
uses: actions/setup-dotnet@v4
2727
with:
28-
dotnet-version: 6.0.x
28+
global-json-file: global.json
2929
- name: Create Release NuGet package
3030
run: |
3131
arrTag=(${GITHUB_REF//\// })
3232
VERSION="${arrTag[2]}"
3333
echo Version: $VERSION
34-
CONFIGURATION=$([ "${VERSION:0:2}" == "v1" ] && echo "ReleaseV1" || echo "Release")
35-
CONFIGURATION=$([ "${VERSION:0:2}" == "v2" ] && echo "ReleaseV2" || echo $CONFIGURATION)
3634
VERSION="${VERSION:1}"
3735
echo Clean Version: $VERSION
38-
echo Configuration: $CONFIGURATION
39-
dotnet pack -v normal -c $CONFIGURATION --include-symbols --include-source -p:PackageVersion=$VERSION -o nupkg EntityFrameworkCore.Triggered.Core.slnf
36+
dotnet pack -v normal -c Release --include-symbols --include-source -p:PackageVersion=$VERSION -o nupkg EntityFrameworkCore.Triggered.Core.slnf
4037
- name: Push to GitHub Feed
4138
run: |
4239
for f in ./nupkg/*.nupkg
@@ -48,4 +45,4 @@ jobs:
4845
for f in ./nupkg/*.nupkg
4946
do
5047
dotnet nuget push $f --source $NUGET_FEED --skip-duplicate --api-key $NUGET_KEY
51-
done
48+
done

CLAUDE.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
EntityFrameworkCore.Triggered is a library that adds trigger support (before/after save hooks) to Entity Framework Core. Triggers react to entity changes during `SaveChanges` via `IBeforeSaveTrigger<T>`, `IAfterSaveTrigger<T>`, and related interfaces.
8+
9+
## Build & Test Commands
10+
11+
```bash
12+
# Build (default is V3 / .NET 6.0)
13+
dotnet build EntityFrameworkCore.Triggered.sln
14+
15+
# Run all tests
16+
dotnet test EntityFrameworkCore.Triggered.sln
17+
18+
# Run a single test project
19+
dotnet test test/EntityFrameworkCore.Triggered.Tests
20+
21+
# Run a specific test
22+
dotnet test test/EntityFrameworkCore.Triggered.Tests --filter "FullyQualifiedName~TriggerSessionTests.RaiseBeforeSaveTriggers"
23+
24+
# Build for V2 (.NET Standard 2.1)
25+
dotnet build EntityFrameworkCore.Triggered.sln -c ReleaseV2
26+
27+
# Build for V1 (.NET Standard 2.0)
28+
dotnet build EntityFrameworkCore.Triggered.sln -c ReleaseV1
29+
30+
# Pack NuGet packages
31+
dotnet pack EntityFrameworkCore.Triggered.sln -c Release
32+
```
33+
34+
## Architecture
35+
36+
### Project Dependency Graph
37+
38+
```
39+
Abstractions <── Core (EntityFrameworkCore.Triggered) <── Extensions
40+
<── Transactions
41+
Transactions.Abstractions <── Transactions
42+
```
43+
44+
- **Abstractions**: Pure interfaces (`IBeforeSaveTrigger<T>`, `IAfterSaveTrigger<T>`, `ITriggerContext<T>`, `ITriggerSession`, `ChangeType`, lifecycle triggers). No EF Core dependency.
45+
- **Core**: Main implementation — `TriggerSession` (orchestrator, ~400 lines), `TriggerService`, `TriggerContext`, trigger discovery, cascade strategies, and EF Core integration via `UseTriggers()`.
46+
- **Extensions**: Assembly scanning for trigger discovery (`AddAssemblyTriggers`).
47+
- **Transactions**: Transaction-scoped triggers (`IBeforeCommitTrigger`, `IAfterCommitTrigger`).
48+
49+
### Key Internal Components
50+
51+
- **TriggerSession** (`src/EntityFrameworkCore.Triggered/TriggerSession.cs`): Core orchestrator that coordinates trigger discovery, invocation, and cascading during SaveChanges.
52+
- **TriggerContextTracker** (`Internal/`): Wraps EF Core's ChangeTracker to discover pending entity changes.
53+
- **TriggerDiscoveryService** (`Internal/`): Resolves registered triggers for entity types, supporting type inheritance and priority ordering.
54+
- **Descriptor classes** (`Internal/Descriptors/`): Handle invocation of specific trigger types (BeforeSave, AfterSave, etc.) via reflection.
55+
- **CascadeStrategies** (`Internal/CascadeStrategies/`): Control re-discovery of changes after triggers modify entities. Default is `EntityAndTypeCascadeStrategy`.
56+
57+
### Registration Entry Points
58+
59+
- `UseTriggers()` on `DbContextOptionsBuilder` — core configuration
60+
- `AddTriggeredDbContext<T>()` / `AddTriggeredDbContextPool<T>()` / `AddTriggeredDbContextFactory<T>()` — service collection helpers in `Extensions/ServiceCollectionExtensions.cs`
61+
62+
## Multi-Version Strategy
63+
64+
The project supports multiple EF Core versions via build configurations and conditional compilation:
65+
66+
| Config | Target | Preprocessor Symbol | EF Core |
67+
|--------|--------|---------------------|---------|
68+
| Release (V3) | net6.0 | `EFCORETRIGGERED3` | 6.0.0 |
69+
| ReleaseV2 | netstandard2.1 | `EFCORETRIGGERED2` | 3.1.x |
70+
| ReleaseV1 | netstandard2.0 | `EFCORETRIGGERED1` | 3.1.x |
71+
72+
Version-specific code uses `#if EFCORETRIGGERED3` guards. The current branch (`v3`) targets V3.
73+
74+
## Build Settings
75+
76+
- **TreatWarningsAsErrors**: enabled globally (`Directory.Build.props`)
77+
- **Nullable reference types**: enabled
78+
- **LangVersion**: 9.0
79+
- **Strong naming**: enabled (signed with `EntityFrameworkCore.Triggered.snk`)
80+
81+
## Test Projects
82+
83+
- `EntityFrameworkCore.Triggered.Tests` — unit tests (xUnit), uses EF Core InMemory provider
84+
- `EntityFrameworkCore.Triggered.IntegrationTests` — full SaveChanges lifecycle tests
85+
- `EntityFrameworkCore.Triggered.Extensions.Tests` — assembly trigger discovery
86+
- `EntityFrameworkCore.Triggered.Transactions.Tests` — transaction trigger behavior
87+
- `EntityFrameworkCore.Triggered.Analyzers.Tests` — Roslyn analyzer tests

Directory.Build.props

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,24 @@
11
<Project>
22

3-
<PropertyGroup>
4-
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
5-
<LangVersion>9.0</LangVersion>
6-
<Nullable>enable</Nullable>
7-
<EnableNETAnalyzers>true</EnableNETAnalyzers>
8-
<Configurations>Debug;Release</Configurations>
9-
<PackageReadmeFile>README.md</PackageReadmeFile>
10-
</PropertyGroup>
3+
<PropertyGroup>
4+
<LangVersion>12</LangVersion>
5+
<Nullable>enable</Nullable>
6+
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
7+
<EnableNETAnalyzers>true</EnableNETAnalyzers>
8+
<PackageReadmeFile>README.md</PackageReadmeFile>
9+
</PropertyGroup>
1110

12-
<PropertyGroup>
13-
<Description>Triggers for EF Core. Respond to changes in your ApplicationDbContext before and after they are committed to the database</Description>
14-
<RepositoryType>Git</RepositoryType>
15-
<RepositoryUrl>https://github.com/koenbeuk/EntityFrameworkCore.Triggered</RepositoryUrl>
16-
<Authors>Koen Bekkenutte</Authors>
17-
<PackageTags>EntityFramework;EFCore;Triggers;SQLServer;SqlLite;CosmosDb;.NET Core;aspnetcore</PackageTags>
18-
<PackageProjectUrl>https://github.com/koenbeuk/EntityFrameworkCore.Triggered</PackageProjectUrl>
19-
</PropertyGroup>
20-
21-
<PropertyGroup>
22-
<EFCoreTriggeredVersion>3</EFCoreTriggeredVersion>
23-
<EFCorePackageVersion>6.0.0</EFCorePackageVersion>
24-
<MicrosoftExtensionsVersion>6.0.0</MicrosoftExtensionsVersion>
25-
</PropertyGroup>
11+
<PropertyGroup>
12+
<Description>Triggers for EF Core. Respond to changes in your ApplicationDbContext before and after they are committed to the database</Description>
13+
<RepositoryType>Git</RepositoryType>
14+
<RepositoryUrl>https://github.com/koenbeuk/EntityFrameworkCore.Triggered</RepositoryUrl>
15+
<Authors>Koen Bekkenutte</Authors>
16+
<PackageTags>EntityFramework;EFCore;Triggers;SQLServer;SqlLite;CosmosDb;.NET Core;aspnetcore</PackageTags>
17+
<PackageProjectUrl>https://github.com/koenbeuk/EntityFrameworkCore.Triggered</PackageProjectUrl>
18+
</PropertyGroup>
2619

27-
<ItemGroup>
28-
<None Include="$(SolutionDir)\README.md" Pack="true" PackagePath="\"></None>
29-
</ItemGroup>
20+
<ItemGroup>
21+
<None Include="$(SolutionDir)\README.md" Pack="true" PackagePath="\" />
22+
</ItemGroup>
3023

3124
</Project>

Directory.Packages.props

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<Project>
2+
<PropertyGroup>
3+
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
4+
</PropertyGroup>
5+
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
6+
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.10" />
7+
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.10" />
8+
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.10" />
9+
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.10" />
10+
</ItemGroup>
11+
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
12+
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
13+
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.0" />
14+
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.0" />
15+
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0" />
16+
</ItemGroup>
17+
<ItemGroup Condition="'$(TargetFramework)' == 'net10.0'">
18+
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="10.0.0" />
19+
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.0" />
20+
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="10.0.0" />
21+
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
22+
</ItemGroup>
23+
<ItemGroup>
24+
<PackageVersion Include="BenchmarkDotNet" Version="0.15.8" />
25+
<PackageVersion Include="coverlet.collector" Version="8.0.1" />
26+
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
27+
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
28+
<PackageVersion Include="Verify.Xunit" Version="31.12.5" />
29+
<PackageVersion Include="xunit" Version="2.9.3" />
30+
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
31+
<PackageVersion Include="ScenarioTests.XUnit" Version="1.0.1" />
32+
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" />
33+
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.8.0" />
34+
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
35+
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Analyzer.Testing" Version="1.1.2" />
36+
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.CodeFix.Testing" Version="1.1.2" />
37+
</ItemGroup>
38+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netstandard2.0</TargetFramework>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" PrivateAssets="all" />
9+
</ItemGroup>
10+
11+
<ItemGroup>
12+
<ProjectReference Include="..\EntityFrameworkCore.Triggered.Analyzers\EntityFrameworkCore.Triggered.Analyzers.csproj" />
13+
</ItemGroup>
14+
15+
</Project>

0 commit comments

Comments
 (0)