|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Essential Development Commands |
| 6 | + |
| 7 | +### Building the Solution |
| 8 | +```powershell |
| 9 | +dotnet restore |
| 10 | +dotnet build -c Release |
| 11 | +``` |
| 12 | + |
| 13 | +### Running Tests |
| 14 | +```powershell |
| 15 | +dotnet test -c Release --no-build |
| 16 | +``` |
| 17 | + |
| 18 | +### Running a Single Test Project |
| 19 | +```powershell |
| 20 | +dotnet test tests/Thinktecture.EntityFrameworkCore.SqlServer.Tests/ -c Release |
| 21 | +``` |
| 22 | + |
| 23 | +## Architecture Overview |
| 24 | + |
| 25 | +This repository extends Entity Framework Core with performance enhancements and testing utilities across multiple database providers. |
| 26 | + |
| 27 | +### Core Package Structure |
| 28 | + |
| 29 | +**Runtime Packages (`src/`)**: |
| 30 | +- `Thinktecture.EntityFrameworkCore.Relational` - Base abstractions and shared functionality |
| 31 | +- `Thinktecture.EntityFrameworkCore.BulkOperations` - Multi-provider bulk operations |
| 32 | +- `Thinktecture.EntityFrameworkCore.SqlServer` - SQL Server specific features |
| 33 | +- `Thinktecture.EntityFrameworkCore.Sqlite` - SQLite specific features |
| 34 | +- `Thinktecture.EntityFrameworkCore.Testing` - Base testing infrastructure |
| 35 | +- `Thinktecture.EntityFrameworkCore.SqlServer.Testing` - SQL Server test helpers |
| 36 | +- `Thinktecture.EntityFrameworkCore.Sqlite.Testing` - SQLite test helpers |
| 37 | + |
| 38 | +**Test Structure (`tests/`)**: |
| 39 | +- Tests mirror the `src/` structure with `.Tests` suffix |
| 40 | +- `TestHelpers` package provides shared test utilities |
| 41 | + |
| 42 | +### Key Architectural Patterns |
| 43 | + |
| 44 | +**Bulk Operations Architecture**: |
| 45 | +- Provider-agnostic interfaces (`IBulkInsertExecutor`, `IBulkUpdateExecutor`, etc.) |
| 46 | +- SQL Server implementation uses `SqlBulkCopy` for inserts and MERGE statements for updates |
| 47 | +- Context factories manage connection lifecycle and transaction handling |
| 48 | +- Strongly-typed options classes inherit from base interfaces |
| 49 | + |
| 50 | +**Temp Tables Architecture**: |
| 51 | +- `ITempTableCreator` creates temp tables with `ITempTableReference` for lifecycle management |
| 52 | +- `ITempTableQuery<T>` wraps `IQueryable<T>` with automatic cleanup via `IAsyncDisposable` |
| 53 | +- Integration with bulk operations via `ITempTableBulkInsertExecutor` |
| 54 | + |
| 55 | +**Multi-Provider Support**: |
| 56 | +- Shared interfaces in BulkOperations with provider-specific implementations |
| 57 | +- SQL Server: Table hints, temp tables, window functions, tenant database support |
| 58 | +- SQLite: Simplified bulk operations, window functions, limitation handling |
| 59 | + |
| 60 | +## Testing Infrastructure |
| 61 | + |
| 62 | +### SQL Server Integration Tests |
| 63 | +- Base class: `IntegrationTestsBase` |
| 64 | +- Mark tests with `[Collection("SqlServerTests")]` for proper isolation |
| 65 | +- Use `SqlServerFixture` for shared connections |
| 66 | +- Capture SQL with `CollectExecutedCommands()` to verify generated queries |
| 67 | + |
| 68 | +### SQLite Integration Tests |
| 69 | +- Base class: `SqliteDbContextIntegrationTests<T>` |
| 70 | +- Use `DbContextProviderFactoryFixture` for database lifecycle management |
| 71 | +- Less isolation requirements compared to SQL Server tests |
| 72 | + |
| 73 | +### Test Patterns |
| 74 | +- xUnit + AwesomeAssertions + NSubstitute + Serilog XUnit sink |
| 75 | +- Naming: `MethodName_Should_DoSomething_When_Condition` |
| 76 | +- Use `ArrangeDbContext`, `ActDbContext`, `AssertDbContext` for different test phases |
| 77 | +- Results written to `test-results/<TargetFramework>/` |
| 78 | + |
| 79 | +## Development Workflows |
| 80 | + |
| 81 | +### Feature Development (Test-First Approach) |
| 82 | +1. **Understand scope**: Identify affected packages in `src/**` and corresponding tests in `tests/**` |
| 83 | +2. **Write failing tests first**: Create unit tests in `tests/<Package>.Tests/**` folder |
| 84 | +3. **Minimal public surface**: Keep APIs `internal` unless cross-package usage is needed |
| 85 | +4. **Server-evaluable queries**: Ensure EF Core operations stay on the server side |
| 86 | +5. **Use appropriate test base**: `IntegrationTestsBase` for SQL Server, `SqliteDbContextIntegrationTests<T>` for SQLite |
| 87 | +6. **Verify SQL generation**: Use `CollectExecutedCommands()` to validate generated SQL |
| 88 | + |
| 89 | +### Bug Fix Workflow |
| 90 | +1. **Reproduce first**: Create a failing test demonstrating the bug |
| 91 | +2. **Minimal fix**: Implement the smallest change to pass the test |
| 92 | +3. **Multi-TFM validation**: Test on both `net8.0` and `net9.0` |
| 93 | + |
| 94 | +## Key Development Guidelines |
| 95 | + |
| 96 | +### EF Core Specifics |
| 97 | +- Keep operations server-evaluable; avoid client evaluation; prefer `IQueryable` over early `ToList()` |
| 98 | +- Never concatenate raw SQL; use `FromSqlInterpolated` or existing parameterized helpers |
| 99 | +- Use `AsNoTracking()` for read-only queries unless state tracking is needed |
| 100 | +- Always provide async APIs with `CancellationToken` for I/O operations; avoid sync-over-async |
| 101 | +- Use EF Core `IDbContextTransaction`/`ExecutionStrategy` patterns for transactions |
| 102 | + |
| 103 | +### Code Conventions |
| 104 | +- Target frameworks: `net8.0` and `net9.0` |
| 105 | +- C# 13.0 with nullable reference types enabled, implicit usings enabled |
| 106 | +- File-scoped namespaces starting with `Thinktecture` and match folder structure |
| 107 | +- Default to `internal` visibility unless cross-package usage is needed |
| 108 | +- Use explicit null checks with `ArgumentNullException.ThrowIfNull()` |
| 109 | +- Expression-bodied members where appropriate; prefer `record` for value-like objects |
| 110 | + |
| 111 | +### Package Management |
| 112 | +- All package versions centralized in `Directory.Packages.props` |
| 113 | +- Reference packages from `.csproj` files without version numbers |
| 114 | +- EF Core 9.x is the current target version (Microsoft.EntityFrameworkCore.*: 9.0.8) |
| 115 | + |
| 116 | +### Provider-Specific Considerations |
| 117 | +- SQL Server: Leverage table hints, temp tables, bulk operations via existing abstractions |
| 118 | +- SQLite: Account for concurrency limitations, DDL locks, missing server features |
| 119 | +- Add conditional code paths only when necessary; maintain consistent API surface where possible |
| 120 | + |
| 121 | +### Essential Patterns |
| 122 | +```csharp |
| 123 | +// Proper async method signature |
| 124 | +public async Task<Result> ProcessAsync(CancellationToken cancellationToken = default) |
| 125 | +{ |
| 126 | + ArgumentNullException.ThrowIfNull(parameter); |
| 127 | + var data = await GetDataAsync(cancellationToken); |
| 128 | + return ProcessData(data); |
| 129 | +} |
| 130 | + |
| 131 | +// Bulk operations usage |
| 132 | +await ActDbContext.BulkInsertAsync(entities); |
| 133 | +await using var tempTable = await ActDbContext.BulkInsertIntoTempTableAsync(values); |
| 134 | + |
| 135 | +// Table hints (SQL Server) |
| 136 | +query.WithTableHints(SqlServerTableHint.NoLock) |
| 137 | + |
| 138 | +// Window functions |
| 139 | +EF.Functions.WindowFunction(function, arg, EF.Functions.PartitionBy(...), EF.Functions.OrderBy(...)) |
| 140 | +``` |
| 141 | + |
| 142 | +## Important Files to Know |
| 143 | + |
| 144 | +- `Thinktecture.EntityFrameworkCore.slnx` - Main solution file |
| 145 | +- `Directory.Packages.props` - Centralized package version management |
| 146 | +- `Directory.Build.props` - Shared MSBuild properties |
| 147 | +- `.github/copilot-instructions.md` - Comprehensive development guidelines |
| 148 | +- Test results are written to `test-results/<TargetFramework>/` |
0 commit comments