Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
952bec9
Update .NET SDK and package dependencies to latest versions
ChrisJollyAU May 23, 2026
1ab5734
Improve Jet string function translation and add string.Join
ChrisJollyAU May 23, 2026
b631f14
Refactor Jet concurrency tests for List<byte> row versions
ChrisJollyAU May 23, 2026
4506f32
Add the Default properties for the type mapping. Helps prepare for co…
ChrisJollyAU Jun 2, 2026
e264a63
Properly handle Date.ToDateTime
ChrisJollyAU Jun 2, 2026
824517c
Scaffold the identity seed and increment
ChrisJollyAU Jun 2, 2026
d130c12
Update tests.
ChrisJollyAU Jun 2, 2026
6e518c8
moretest fixes
ChrisJollyAU Jun 2, 2026
43f063a
Add JetCSharpRuntimeAnnotationCodeGenerator and docs
ChrisJollyAU Jun 6, 2026
7d1e141
Bump version to 10.0.1 for servicing release
ChrisJollyAU Jun 6, 2026
a1a8b3f
Improve Jet SQL boolean/numeric conversion handling
ChrisJollyAU Jun 6, 2026
76b9fd1
Update identity column seed/increment test assertions
ChrisJollyAU Jun 6, 2026
a973955
Change default TimeSpan mapping to 'datetime' type
ChrisJollyAU Jun 6, 2026
56b19f7
Update "long" type mapping to use integer, not bigint
ChrisJollyAU Jun 6, 2026
e9c4066
revert this baseline back to datetime. missed in a prev commit
ChrisJollyAU Jun 7, 2026
16f866c
Update HasFlag enum tests for Jet/ACE SQL compatibility
ChrisJollyAU Jun 7, 2026
6384523
Refactor parameter handling in JetCommand
ChrisJollyAU Jun 7, 2026
d9caaba
Update test
ChrisJollyAU Jun 7, 2026
be279b6
Add CLAUDE.md with project guidance for Claude Code
ChrisJollyAU Jun 7, 2026
ba5e7ba
update green tests
ChrisJollyAU Jun 8, 2026
b7f816c
Revert "Refactor parameter handling in JetCommand"
ChrisJollyAU Jun 8, 2026
31c95fb
Improve resource management and SQL param assertions
ChrisJollyAU Jun 8, 2026
69fe885
update tests
ChrisJollyAU Jun 8, 2026
495765e
remove unneeded files
ChrisJollyAU Jun 9, 2026
6512797
Improve GetGuid robustness and Guid handling in reader
ChrisJollyAU Jun 9, 2026
10e11b3
remove bigint/int64 to make it work
ChrisJollyAU Jun 9, 2026
de25c73
Add AGENTS.md, refactor postprocessor, skip collation tests
ChrisJollyAU Jun 11, 2026
5f4f57c
Refactor Jet join SQL generation for correct grouping
ChrisJollyAU Jun 11, 2026
259c1ff
Split FunctionalTests into Query/Non-Query shards
ChrisJollyAU Jun 15, 2026
31992e2
fix test
ChrisJollyAU Jun 16, 2026
f351b45
Remove a primitve collection test class as Jet doesnt support json
ChrisJollyAU Jun 16, 2026
0685104
Refactor Jet value gen strategy logic and FK constraint drops
ChrisJollyAU Jun 16, 2026
ae33d23
Optimize LongCount() > 0 to Any() for Jet queries
ChrisJollyAU Jun 18, 2026
dd86811
remove unneeded
ChrisJollyAU Jun 20, 2026
3f18d11
Fix Compiled models tests
ChrisJollyAU Jun 24, 2026
70ee49d
Fix REPLACE() null handling for Access/Jet SQL
ChrisJollyAU Jun 24, 2026
b9cf406
Handle identity annotations for compiled models
ChrisJollyAU Jun 24, 2026
cb2fc7c
Refactor connection string handling and add validation
ChrisJollyAU Jun 30, 2026
1913348
Update deps, refactor JetConnection string normalization
ChrisJollyAU Jun 30, 2026
e2e1806
update green tests for stuff removed from the test suite
ChrisJollyAU Jun 30, 2026
ee0379e
Update README: clarify usage, requirements, and CI feeds
ChrisJollyAU Jul 1, 2026
870a889
Update CI workflows: action versions & test sharding
ChrisJollyAU Jul 1, 2026
3418ee0
[GitHub Actions] Update green tests.
invalid-email-address Jul 1, 2026
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
6 changes: 6 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Copilot Instructions

## Project Guidelines
- This project (EntityFrameworkCore.Jet) targets the Microsoft Access Jet/ACE database engine, not SQL Server. Generated SQL, type mappings, and literals must be Jet/ACE-compliant (e.g. decimal/currency instead of bigint, #...# date literals, TIMEVALUE()). Note: Access 2016+ (ACE) does have a native BIGINT (Large Number) type, which is a SIGNED 64-bit integer and cannot hold unsigned values like ulong.MaxValue; unsigned ulong/uint should map to decimal(20,0) to avoid overflow. Provider distinctions are OLE DB / ODBC via the ACE/Jet driver rather than SqlClient. Do not assume SQL Server/T-SQL semantics.
- Jet/Access SQL dialect used in this project does not support COALESCE or NZ. When rewriting queries for Jet, prefer using IIF(<expr> IS NULL, <default>, <expr>) or 'CASE WHEN <expr> IS NULL THEN <default> ELSE <expr> END' instead.
- Deferred enhancement for EntityFrameworkCore.Jet: add ACE engine-version detection so that on Access 2016+ the provider can map to native BIGINT (signed long; unsigned ulong/uint still go to decimal(20,0)) and native DATETIME2, while falling back to decimal(20,0)/legacy datetime on older ACE versions. Not a priority right now.
4 changes: 2 additions & 2 deletions .github/workflows/auto_commit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ jobs:
if: github.event.workflow_run.conclusion == 'success' && (github.event.workflow_run.head_commit.author.email != 'github-actions@github.com' || github.event.workflow_run.head_commit.message != '[GitHub Actions] Update green tests.')
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
repository: ${{ github.event.workflow_run.head_repository.full_name }}
ref: ${{ github.event.workflow_run.head_branch }}
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0
- name: 'Download Green Tests'
id: DownloadGreenTests
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
script: |
var allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
Expand Down
154 changes: 125 additions & 29 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
run: |
echo 'EventName: ${{ github.event_name }}'
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: ${{ env.checkoutFetchDepth }}
- name: 'Get Head Commit Info'
Expand Down Expand Up @@ -76,7 +76,7 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Set additional variables
shell: pwsh
run: |
Expand Down Expand Up @@ -229,30 +229,31 @@ jobs:
run: |
$env:EFCoreJet_DefaultConnection = '${{ env.defaultConnection }}'
& '${{ env.dotnetExecutable }}' test .\test\EFCore.Jet.Tests --configuration '${{ env.buildConfiguration }}' -p:FixedTestOrder=${{ env.deterministicTests }} --logger trx --verbosity detailed --blame-hang-timeout 3m
- name: 'Run Tests: EFCore.Jet.FunctionalTests'
- name: 'Run Tests: EFCore.Jet.FunctionalTests (Shard 1 - Query Core)'
if: always() && env.skipTests != 'true'
shell: pwsh
run: |
$shardDir = '.\test\EFCore.Jet.FunctionalTests\TestResults\shard1'

for ($i = 0; $i -lt 3; $i++) {
if (Test-Path '.\test\EFCore.Jet.FunctionalTests\TestResults' -PathType Container) {
Get-ChildItem '.\test\EFCore.Jet.FunctionalTests\TestResults' | Remove-Item -Recurse -Force
if (Test-Path $shardDir -PathType Container) {
Get-ChildItem $shardDir | Remove-Item -Recurse -Force
}

$env:EFCoreJet_DefaultConnection = '${{ env.defaultConnection }}'
& '${{ env.dotnetExecutable }}' test .\test\EFCore.Jet.FunctionalTests --configuration '${{ env.buildConfiguration }}' -p:FixedTestOrder=${{ env.deterministicTests }} --logger trx --verbosity detailed --blame-hang-timeout 3m
& '${{ env.dotnetExecutable }}' test .\test\EFCore.Jet.FunctionalTests --configuration '${{ env.buildConfiguration }}' -p:FixedTestOrder=${{ env.deterministicTests }} --logger trx --verbosity detailed --blame-hang-timeout 3m --results-directory $shardDir --filter "FullyQualifiedName~.FunctionalTests.Query.&FullyQualifiedName!~.FunctionalTests.Query.Associations.&FullyQualifiedName!~.FunctionalTests.Query.Translations."

#
# Check for test runner crashes:
#

$testResultsDir = '.\test\EFCore.Jet.FunctionalTests\TestResults'
$currentTestRunTrx = Get-ChildItem $testResultsDir -Filter '*.trx' | Sort-Object LastWriteTime | Select-Object -Last 1
$currentTestRunTrx = Get-ChildItem $shardDir -Filter '*.trx' | Sort-Object LastWriteTime | Select-Object -Last 1
if ($null -eq $currentTestRunTrx) {
echo 'Test runner log file is missing.'
exit 3
}

$currentTestRunDir = Join-Path $testResultsDir $currentTestRunTrx.BaseName
$currentTestRunDir = Join-Path $shardDir $currentTestRunTrx.BaseName
if (Test-Path $currentTestRunDir) {
if ($null -ne (Get-ChildItem $currentTestRunDir -Filter 'Sequence_*' -Recurse)) {
# Split string because searching the log for that phrase should only show actual crashes and not this line.
Expand All @@ -267,7 +268,97 @@ jobs:

$establishedGreenTestsFilePath = ".\test\EFCore.Jet.FunctionalTests\GreenTests\ace_${{ matrix.aceVersion }}_$('${{ matrix.dataAccessProviderType }}'.Replace(' ', '').ToLowerInvariant())_${{ matrix.aceArchitecture }}.txt"
$failIfKeepsCrashing = Test-Path $establishedGreenTestsFilePath


if ($i -ge 3 -and $failIfKeepsCrashing) {
echo 'Test runner keeps crashing.'
exit 2
}
exit 0
- name: 'Run Tests: EFCore.Jet.FunctionalTests (Shard 2 - Query Associations and Translations)'
if: always() && env.skipTests != 'true'
shell: pwsh
run: |
$shardDir = '.\test\EFCore.Jet.FunctionalTests\TestResults\shard2'

for ($i = 0; $i -lt 3; $i++) {
if (Test-Path $shardDir -PathType Container) {
Get-ChildItem $shardDir | Remove-Item -Recurse -Force
}

$env:EFCoreJet_DefaultConnection = '${{ env.defaultConnection }}'
& '${{ env.dotnetExecutable }}' test .\test\EFCore.Jet.FunctionalTests --configuration '${{ env.buildConfiguration }}' -p:FixedTestOrder=${{ env.deterministicTests }} --logger trx --verbosity detailed --blame-hang-timeout 3m --results-directory $shardDir --filter "FullyQualifiedName~.FunctionalTests.Query.Associations.|FullyQualifiedName~.FunctionalTests.Query.Translations."

#
# Check for test runner crashes:
#

$currentTestRunTrx = Get-ChildItem $shardDir -Filter '*.trx' | Sort-Object LastWriteTime | Select-Object -Last 1
if ($null -eq $currentTestRunTrx) {
echo 'Test runner log file is missing.'
exit 3
}

$currentTestRunDir = Join-Path $shardDir $currentTestRunTrx.BaseName
if (Test-Path $currentTestRunDir) {
if ($null -ne (Get-ChildItem $currentTestRunDir -Filter 'Sequence_*' -Recurse)) {
# Split string because searching the log for that phrase should only show actual crashes and not this line.
echo ('Test runner cras' + 'hed.')
continue
}
}

echo 'Test runner ran until the end.'
break
}

$establishedGreenTestsFilePath = ".\test\EFCore.Jet.FunctionalTests\GreenTests\ace_${{ matrix.aceVersion }}_$('${{ matrix.dataAccessProviderType }}'.Replace(' ', '').ToLowerInvariant())_${{ matrix.aceArchitecture }}.txt"
$failIfKeepsCrashing = Test-Path $establishedGreenTestsFilePath

if ($i -ge 3 -and $failIfKeepsCrashing) {
echo 'Test runner keeps crashing.'
exit 2
}
exit 0
- name: 'Run Tests: EFCore.Jet.FunctionalTests (Shard 3 - Non-Query)'
if: always() && env.skipTests != 'true'
shell: pwsh
run: |
$shardDir = '.\test\EFCore.Jet.FunctionalTests\TestResults\shard3'

for ($i = 0; $i -lt 3; $i++) {
if (Test-Path $shardDir -PathType Container) {
Get-ChildItem $shardDir | Remove-Item -Recurse -Force
}

$env:EFCoreJet_DefaultConnection = '${{ env.defaultConnection }}'
& '${{ env.dotnetExecutable }}' test .\test\EFCore.Jet.FunctionalTests --configuration '${{ env.buildConfiguration }}' -p:FixedTestOrder=${{ env.deterministicTests }} --logger trx --verbosity detailed --blame-hang-timeout 3m --results-directory $shardDir --filter "FullyQualifiedName!~.FunctionalTests.Query."

#
# Check for test runner crashes:
#

$currentTestRunTrx = Get-ChildItem $shardDir -Filter '*.trx' | Sort-Object LastWriteTime | Select-Object -Last 1
if ($null -eq $currentTestRunTrx) {
echo 'Test runner log file is missing.'
exit 3
}

$currentTestRunDir = Join-Path $shardDir $currentTestRunTrx.BaseName
if (Test-Path $currentTestRunDir) {
if ($null -ne (Get-ChildItem $currentTestRunDir -Filter 'Sequence_*' -Recurse)) {
# Split string because searching the log for that phrase should only show actual crashes and not this line.
echo ('Test runner cras' + 'hed.')
continue
}
}

echo 'Test runner ran until the end.'
break
}

$establishedGreenTestsFilePath = ".\test\EFCore.Jet.FunctionalTests\GreenTests\ace_${{ matrix.aceVersion }}_$('${{ matrix.dataAccessProviderType }}'.Replace(' ', '').ToLowerInvariant())_${{ matrix.aceArchitecture }}.txt"
$failIfKeepsCrashing = Test-Path $establishedGreenTestsFilePath

if ($i -ge 3 -and $failIfKeepsCrashing) {
echo 'Test runner keeps crashing.'
exit 2
Expand All @@ -280,51 +371,56 @@ jobs:
Get-ChildItem -Filter '*.trx' -Recurse | Sort-Object LastWriteTime | ForEach { Rename-Item $_.FullName "ace_${{ matrix.aceVersion }}_$('${{ matrix.dataAccessProviderType }}'.Replace(' ', '').ToLowerInvariant())_${{ matrix.aceArchitecture }}_$($_.Name)" -Verbose }
- name: 'Upload Test Results'
if: always() && env.skipTests != 'true' && env.uploadTestResults == 'true'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: test-results_${{ env.matrixId }}
path: |
test\EFCore.Jet.Data.Tests\TestResults\*.trx
test\EFCore.Jet.FunctionalTests\TestResults\*.trx
test\EFCore.Jet.FunctionalTests\TestResults\**\*.trx
test\EFCore.Jet.Tests\TestResults\*.trx
- name: 'Check Tests: EFCore.Jet.FunctionalTests'
if: env.skipTests != 'true'
shell: pwsh
run: |
# Create text file with all tests that passed.
# Collect and merge test results from all shards.
$testResultsDir = '.\test\EFCore.Jet.FunctionalTests\TestResults'
$currentTestRunTrx = Get-ChildItem $testResultsDir -Filter '*.trx' | Sort-Object LastWriteTime | Select-Object -Last 1
$allTrxFiles = @(Get-ChildItem $testResultsDir -Filter '*.trx' -Recurse)

if ($null -eq $currentTestRunTrx) {
echo 'Test runner log file is missing.'
if ($allTrxFiles.Count -eq 0) {
echo 'No test result files found.'
exit 3
}

$allTestsFilePath = Join-Path $currentTestRunTrx.DirectoryName ($currentTestRunTrx.BaseName + '_All.txt')
(Select-Xml -Path $currentTestRunTrx.FullName -XPath "//ns:UnitTestResult" -Namespace @{"ns"="http://microsoft.com/schemas/VisualStudio/TeamTest/2010"}).Node | Sort-Object -Property testName -CaseSensitive | ForEach-Object { "$($_.outcome -eq 'Passed' ? 'P' : $_.outcome -eq 'NotExecuted' ? 'N' : $_.outcome -eq 'Failed' ? 'F' : 'U') $($_.testName)" } | Add-Content $allTestsFilePath
$allNodes = @()
foreach ($trxFile in $allTrxFiles) {
$allNodes += (Select-Xml -Path $trxFile.FullName -XPath "//ns:UnitTestResult" -Namespace @{"ns"="http://microsoft.com/schemas/VisualStudio/TeamTest/2010"}).Node
}

$allTestsFilePath = Join-Path $testResultsDir 'combined_All.txt'
$allNodes | Sort-Object -Property testName -CaseSensitive | ForEach-Object { "$($_.outcome -eq 'Passed' ? 'P' : $_.outcome -eq 'NotExecuted' ? 'N' : $_.outcome -eq 'Failed' ? 'F' : 'U') $($_.testName)" } | Set-Content $allTestsFilePath

$greenTestsFilePath = Join-Path $currentTestRunTrx.DirectoryName ($currentTestRunTrx.BaseName + '_Passed.txt')
Get-Content $allTestsFilePath | Where-Object { $_.StartsWith('P ') } | ForEach-Object { $_.Substring(2) } | Add-Content $greenTestsFilePath
$greenTestsFilePath = Join-Path $testResultsDir 'combined_Passed.txt'
Get-Content $allTestsFilePath | Where-Object { $_.StartsWith('P ') } | ForEach-Object { $_.Substring(2) } | Set-Content $greenTestsFilePath

# Compare test file against previously committed file.
$establishedGreenTestsFilePath = ".\test\EFCore.Jet.FunctionalTests\GreenTests\ace_${{ matrix.aceVersion }}_$('${{ matrix.dataAccessProviderType }}'.Replace(' ', '').ToLowerInvariant())_${{ matrix.aceArchitecture }}.txt"

if (Test-Path $establishedGreenTestsFilePath) {
$diffResult = Compare-Object (Get-Content $establishedGreenTestsFilePath) (Get-Content $greenTestsFilePath)

$notGreenAnymore = $diffResult | Where-Object { $_.SideIndicator -eq '<=' } | Select-Object -ExpandProperty InputObject
if ($null -ne $notGreenAnymore) {
echo "`nThe following $(@($notGreenAnymore).Length) tests passed in previous runs, but didn't pass in this run:`n"
$notGreenAnymore
exit 1
}

echo 'All tests that passed in previous runs still passed in this run.'

$newlyGreenTests = $diffResult | Where-Object { $_.SideIndicator -eq '=>' } | Select-Object -ExpandProperty InputObject
if ($newlyGreenTests.Length -gt 0) {
Copy-Item $greenTestsFilePath $establishedGreenTestsFilePath -Force -Verbose

echo "`nThe following new tests passed that did not pass before:`n"
$newlyGreenTests

Expand All @@ -335,7 +431,7 @@ jobs:
echo 'Check succeeded.'
- name: 'Upload Green Tests'
if: env.commitGreenTestsFile != '' && env.autoCommitGreenTests == 'true'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: green-tests_${{ env.matrixId }}
path: ${{ env.commitGreenTestsFile }}
Expand All @@ -349,7 +445,7 @@ jobs:
steps:
- name: 'Check Test Results Artifacts'
id: CheckTestResultsArtifacts
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
script: |
var allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
Expand All @@ -369,14 +465,14 @@ jobs:
- name: 'Merge Test Results'
id: MergeTestResults
if: steps.CheckTestResultsArtifacts.outputs.artifactsAvailable == 'true'
uses: actions/upload-artifact/merge@v4
uses: actions/upload-artifact/merge@v6
with:
name: test-results
pattern: test-results_*
delete-merged: true
- name: 'Check Green Tests Artifacts'
id: CheckGreenTestsArtifacts
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
script: |
var allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
Expand All @@ -396,7 +492,7 @@ jobs:
- name: 'Merge Green Tests'
id: MergeGreenTests
if: steps.CheckGreenTestsArtifacts.outputs.artifactsAvailable == 'true'
uses: actions/upload-artifact/merge@v4
uses: actions/upload-artifact/merge@v6
with:
name: green-tests
pattern: green-tests_*
Expand All @@ -418,7 +514,7 @@ jobs:
# echo $env:NEEDS_CONTEXT
- name: 'Download Green Tests'
if: needs.MergeArtifacts.outputs.greenTestsAvailable == 'true'
uses: actions/download-artifact@v4
uses: actions/download-artifact@v7
with:
name: green-tests
path: green-tests
Expand Down
Loading