Skip to content

Commit 36e7989

Browse files
authored
Merge pull request #11 from DirectSQL/tryCopilot
Add Copilot repository instructions
2 parents fa267eb + a881001 commit 36e7989

1 file changed

Lines changed: 29 additions & 0 deletions

File tree

.github/copilot-instructions.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# DirectSQL Copilot Instructions
2+
3+
## Build and test
4+
5+
- Build the solution from the repo root with `dotnet build --configuration Release`.
6+
- Run the full test suite with `dotnet test --configuration Release`.
7+
- Run a single MSTest with `dotnet test TestSqlLiteDatabase/TestSqlLiteDatabase.csproj --filter FullyQualifiedName~TestSqlLiteDatabase.QueryTest.TestQuery`.
8+
- The projects target `net8.0`. CI uses .NET 8.0.100, and `global.json` allows rolling forward from 7.0.100 to a newer major SDK.
9+
- `DirectSQL/DirectSQL.csproj` has `GeneratePackageOnBuild=true`, so builds also produce a NuGet package in `DirectSQL/bin/<Configuration>/`.
10+
- In the current dependency set, SQLite tests fail on macOS before assertions run because `System.Data.SQLite.Core` cannot load `SQLite.Interop.dll`.
11+
12+
## High-level architecture
13+
14+
- `DirectSQL/Database.cs` is the core of the library. It owns connection lifecycle (`Process`, `ProcessAsync`), transaction wrappers, parameter creation/conversion, and the provider-agnostic SQL helpers (`ExecuteNonQuery`, `ExecuteScalar`, `Query`, `LoadSqlResult`, and the `FormattableString` overloads).
15+
- Each database-specific entry point is a thin subclass of `Database<...>` under `DirectSQL/SqlLite`, `DirectSQL/SqlServer`, `DirectSQL/npgsql`, `DirectSQL/MySql`, `DirectSQL/DB2`, and `DirectSQL/Odbc`. These classes mostly capture a connection string and implement `CreateConnection()`.
16+
- `DirectSQL/SqlResult.cs` wraps the active `IDataReader` and exposes the current row as `dynamic`, tuple arrays, typed projections, and enumerable loaders. This is the main abstraction for reading query results.
17+
- The normal execution flow is: instantiate a concrete provider database -> enter `Process(...)` / `ProcessAsync(...)` to get an open connection -> call static query helpers on the provider type -> let `Database.cs` build the command and parameters -> read rows through `SqlResult`.
18+
- `LoadSqlResult*` convenience APIs are thin wrappers over `Query(...)` that materialize the cursor into `dynamic[]`; they do not introduce a separate query pipeline.
19+
- Error handling is centralized in `Database.Transaction(...)` and `Database.TransactionAsync(...)`: exceptions from the callback are wrapped in `DatabaseException`, while the low-level command and reader behavior remains straight ADO.NET.
20+
- `TestSqlLiteDatabase` is the only test project and doubles as the main executable specification of library behavior. Most usage patterns in the README are mirrored there.
21+
22+
## Key conventions
23+
24+
- Treat the concrete `*Database` class as the entry point for connection management, then use static methods on that same concrete type inside the callback. The common pattern is `db.Process((conn, tran) => { SqlLiteDatabase.Query(...); })`, not instance methods for query execution.
25+
- Transaction callbacks are manual-commit. `Process((conn, tran) => ...)` and `Database.Transaction(...)` provide a transaction object, but the library does not commit for you; tests that need persistence call `tran.Commit()` explicitly and use `tran.Rollback()` explicitly for rollback scenarios. The library only rolls back automatically when it catches an exception and rethrows `DatabaseException`.
26+
- `SqlResult` is cursor-based. Call `result.Next()` before reading `ResultValues` or `ResultTuples`; attempting to read row values before the first `Next()` or after the cursor is exhausted raises the underlying reader error. `ResultValues` and `ResultTuples` are cached for the current row and reset on the next `Next()`.
27+
- Prefer the built-in parameter helpers over handwritten command setup. The codebase uses tuple parameters like `new (string, object)[] { ("@val1", value) }` and `CreateParameter(...)` when an explicit `DbType` is needed.
28+
- Prefer the `FormattableString` helpers when authoring inline SQL in code. `ExecuteFormattableNonQuery`, `ExecuteFormattableScalar`, `QueryFormattable`, and `LoadFormattableSqlResult` rewrite interpolated values into generated bound parameters like `@0`, `@1`, and tests assert against that rewritten SQL.
29+
- The async APIs are wrappers around synchronous ADO.NET work via `Task.Run`, not provider-native async I/O. Keep that in mind when changing behavior or adding new async surfaces.

0 commit comments

Comments
 (0)