Skip to content

Commit d972059

Browse files
committed
Add claude.md with project conventions and build instructions
https://claude.ai/code/session_0147Z5VzzZpX1pUfaAapNZie
1 parent 0c455bb commit d972059

1 file changed

Lines changed: 51 additions & 0 deletions

File tree

claude.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# EntityFramework.Exceptions
2+
3+
Typed exception handling for Entity Framework Core. Converts database-specific errors into strongly-typed .NET exceptions instead of generic `DbUpdateException`.
4+
5+
## Build & Test
6+
7+
```bash
8+
dotnet restore # Restore NuGet dependencies
9+
dotnet build --no-restore # Build all projects
10+
dotnet test --no-build # Run tests (requires Docker for Testcontainers)
11+
```
12+
13+
Tests use **Testcontainers** and require a running Docker daemon. Each database provider (SQL Server, PostgreSQL, MySQL, Oracle, SQLite) spins up its own container.
14+
15+
## Project Structure
16+
17+
The solution (`EntityFramework.Exceptions.slnx`) has two main layers:
18+
19+
- **DbExceptionClassifier/** — Database-specific error code classification. Each provider implements `IDbExceptionClassifier` to map native error codes to a `DatabaseError` enum.
20+
- `Common/``IDbExceptionClassifier` interface
21+
- `SqlServer/`, `PostgreSQL/`, `MySQL/`, `MySQL.Pomelo/`, `Oracle/`, `Sqlite/` — Provider implementations
22+
23+
- **EntityFramework.Exceptions/** — EF Core integration via interceptors. Catches `DbException`, classifies it, and throws a typed exception.
24+
- `Common/` — Base `ExceptionProcessorInterceptor<T>`, exception classes (`UniqueConstraintException`, `CannotInsertNullException`, `MaxLengthExceededException`, `NumericOverflowException`, `ReferenceConstraintException`), `ExceptionFactory`
25+
- `SqlServer/`, `PostgreSQL/`, `MySQL/`, `MySQL.Pomelo/`, `Oracle/`, `Sqlite/` — Provider-specific interceptors and `UseExceptionProcessor()` extension methods
26+
- `Tests/` — xUnit test suite using Testcontainers
27+
28+
- **Directory.Build.props** — Shared build properties (target framework, version, NuGet metadata). All non-Common projects automatically reference their corresponding Common project.
29+
30+
## Architecture
31+
32+
1. **Interceptor pattern**: `ExceptionProcessorInterceptor<TProviderException>` implements `IDbCommandInterceptor` and `ISaveChangesInterceptor`
33+
2. **Classification**: Each database provider has an `IDbExceptionClassifier` that maps native error codes to `DatabaseError` enum values
34+
3. **Factory**: `ExceptionFactory` creates the appropriate typed exception
35+
4. **Extension methods**: Each provider exposes `UseExceptionProcessor()` on `DbContextOptionsBuilder`
36+
37+
## Code Conventions
38+
39+
- **C# / .NET 8.0** with file-scoped namespaces, primary constructors, nullable reference types, and implicit usings
40+
- **Naming**: `[Database]ExceptionClassifier`, `[Database]ExceptionProcessorInterceptor`, `ExceptionProcessorExtensions.UseExceptionProcessor()`
41+
- **Test naming**: `[Scenario]Throws[ExceptionType]` (e.g., `UniqueColumnViolationThrowsUniqueConstraintException`)
42+
- **MySQL.Pomelo** shares source files with **MySQL** via `<Link>` in .csproj and uses `#if POMELO` preprocessor directive
43+
- Exception classes follow a standard pattern: inherit `DbUpdateException`, provide all standard constructor overloads, and optionally expose `ConstraintName`, `ConstraintProperties`, and `SchemaQualifiedTableName` properties
44+
45+
## Testing Notes
46+
47+
- Base test class `DatabaseTests` defines ~12 virtual test methods; provider-specific test classes inherit and override as needed
48+
- **SQLite** does not populate `ConstraintName`/`ConstraintProperties` and does not enforce numeric overflow
49+
- **SQL Server** skips numeric overflow tests (`ArgumentException` from SqlClient)
50+
- **MySQL** primary key violations do not populate constraint properties
51+
- Test fixtures use `IAsyncLifetime` for container lifecycle management

0 commit comments

Comments
 (0)