# @tsonic/efcore

TypeScript type definitions for **Entity Framework Core 10** (`Microsoft.EntityFrameworkCore.*`) for use with the **Tsonic** compiler (TypeScript → .NET).

This package is generated by `tsbindgen` from the official NuGet assemblies and is intended to give you an editor-friendly, strongly typed surface while compiling to real EF Core APIs.

## What this package is (and isn’t)

- ✅ **It is** a TypeScript type package (`.d.ts`) + ESM stubs for the EF Core assemblies.
- ❌ **It is not** a JavaScript runtime implementation of EF Core (the `.js` files are module stubs for type-only use).
- ✅ **You still need** the actual **.NET assemblies** via NuGet in your Tsonic workspace (see below).

## Install (types)

```bash
npm install @tsonic/efcore @tsonic/dotnet @tsonic/core
```

## Use with Tsonic (recommended)

If you want a deterministic “one command” setup for both the **.NET assemblies** and the **TypeScript bindings**, use `tsonic add nuget` and pass this package as the `types` argument:

```bash
tsonic add nuget Microsoft.EntityFrameworkCore <version> @tsonic/efcore
```

If you omit the `@tsonic/efcore` argument, Tsonic will generate bindings locally instead.

### Providers

Pick the provider that matches your database:

- SQLite: `@tsonic/efcore-sqlite`
- SQL Server: `@tsonic/efcore-sqlserver`
- PostgreSQL (Npgsql): `@tsonic/efcore-npgsql`

Example:

```bash
tsonic add nuget Microsoft.EntityFrameworkCore.Sqlite <version> @tsonic/efcore-sqlite
```

## Imports

The package is shipped as **ESM**. Import EF Core namespaces via explicit module paths:

```ts
import { DbContext, DbContextOptions, DbSet } from "@tsonic/efcore/Microsoft.EntityFrameworkCore.js";
```

Provider-specific APIs come from the provider package:

```ts
import { SqliteDbContextOptionsBuilderExtensions } from "@tsonic/efcore-sqlite/Microsoft.EntityFrameworkCore.js";
```

## LINQ + EF extension methods (idiomatic queries)

EF Core relies heavily on **extension methods** (LINQ operators like `Where`/`Select` and EF async operators like `CountAsync`/`ToArrayAsync`).

In Tsonic, you opt into a “C# using semantics” extension surface by wrapping the receiver with `asinterface<...>` and the generated `ExtensionMethods` helpers:

```ts
import { asinterface } from "@tsonic/core/lang.js";
import type { ExtensionMethods as Linq } from "@tsonic/dotnet/System.Linq.js";
import type { ExtensionMethods as Ef } from "@tsonic/efcore/Microsoft.EntityFrameworkCore.js";
import type { DbSet } from "@tsonic/efcore/Microsoft.EntityFrameworkCore.js";

type DbSetQuery<T> = Ef<Linq<DbSet<T>>>;

// Example: turn a DbSet<T> into something that has LINQ + EF async operators.
const q = asinterface<DbSetQuery<PostEntity>>(db.posts);

const pageviews = await q.Where((p) => p.Published === true).CountAsync();
const rows = await q.Where((p) => p.Published === true).ToArrayAsync();
```

You can always call extension methods via their static classes as well, but the pattern above gives you the most idiomatic “instance-style” call sites.

## Example

Minimal `DbContext` + options:

```ts
import { DbContext, DbContextOptions, DbContextOptionsBuilder, DbSet } from "@tsonic/efcore/Microsoft.EntityFrameworkCore.js";
import { SqliteDbContextOptionsBuilderExtensions } from "@tsonic/efcore-sqlite/Microsoft.EntityFrameworkCore.js";

export class BlogDbContext extends DbContext {
  get posts(): DbSet<PostEntity> {
    return this.Set<PostEntity>();
  }

  constructor(options: DbContextOptions) {
    super(options);
  }
}

export const createDbOptions = (dbPath: string): DbContextOptions => {
  const optionsBuilder = new DbContextOptionsBuilder();
  SqliteDbContextOptionsBuilderExtensions.UseSqlite(optionsBuilder, `Data Source=${dbPath}`);
  return optionsBuilder.Options;
};
```

## Versioning

This repo is versioned by **.NET major**:

- .NET 10 → npm: `@tsonic/efcore@10.x`

## Development (regenerating bindings)

This repo is generated from NuGet assemblies:

```bash
npm install
npm run generate:10
```

## License

MIT
