Entity Framework Core Provider
CSharpDB.EntityFrameworkCore is an embedded-only Entity Framework Core 10 provider built on top of CSharpDB.Data. Use standard EF Core DbContext, migrations, change tracking, and LINQ patterns against local CSharpDB databases.
Install
dotnet add package CSharpDB.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.Design
Microsoft.EntityFrameworkCore.Design is recommended in the application project so dotnet ef can run design-time commands cleanly.
Basic Usage
Configure your context with UseCSharpDb(...).
using CSharpDB.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
public sealed class BloggingContext : DbContext
{
private readonly string? _connectionString;
public BloggingContext(string databasePath)
=> _connectionString = $"Data Source={databasePath}";
public BloggingContext(DbContextOptions<BloggingContext> options)
: base(options)
{
}
public DbSet<Blog> Blogs => Set<Blog>();
public DbSet<Post> Posts => Set<Post>();
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured && _connectionString is not null)
optionsBuilder.UseCSharpDb(_connectionString);
}
}
public sealed class Blog
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public List<Post> Posts { get; set; } = [];
}
public sealed class Post
{
public int Id { get; set; }
public int BlogId { get; set; }
public string Title { get; set; } = string.Empty;
public Blog Blog { get; set; } = null!;
}
Then use EF Core as usual.
await using var db = new BloggingContext("blogging.db");
await db.Database.EnsureCreatedAsync();
db.Blogs.Add(new Blog
{
Name = "Engineering",
Posts = [new Post { Title = "Hello from CSharpDB EF Core" }]
});
await db.SaveChangesAsync();
var blogs = await db.Blogs
.Include(blog => blog.Posts)
.OrderBy(blog => blog.Name)
.ToListAsync();
Existing Connections and In-Memory Databases
You can pass an existing CSharpDbConnection. This is required for a private :memory: database because the database lives as long as the connection stays open.
using CSharpDB.Data;
using CSharpDB.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
await using var connection = new CSharpDbConnection("Data Source=:memory:");
await connection.OpenAsync();
var options = new DbContextOptionsBuilder<BloggingContext>()
.UseCSharpDb(connection)
.Options;
await using var db = new BloggingContext(options);
await db.Database.EnsureCreatedAsync();
Embedded Storage Tuning
The EF Core provider can pass embedded engine tuning down into the CSharpDbConnection it creates. Use named presets and embedded open modes when you want discoverable, compile-checked settings.
using CSharpDB.Data;
using CSharpDB.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
var options = new DbContextOptionsBuilder<BloggingContext>()
.UseCSharpDb(
"Data Source=blogging.db",
csharpdb =>
{
csharpdb.UseStoragePreset(CSharpDbStoragePreset.WriteOptimized);
csharpdb.UseEmbeddedOpenMode(CSharpDbEmbeddedOpenMode.HybridIncrementalDurable);
})
.Options;
Use full engine options when you need exact storage composition.
using CSharpDB.Engine;
using CSharpDB.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
var directOptions = new DatabaseOptions()
.ConfigureStorageEngine(builder => builder.UseWriteOptimizedPreset());
var options = new DbContextOptionsBuilder<BloggingContext>()
.UseCSharpDb(
"Data Source=blogging.db",
csharpdb => csharpdb.UseDirectDatabaseOptions(directOptions))
.Options;
Provider Builder Methods
UseDirectDatabaseOptions(DatabaseOptions)UseHybridDatabaseOptions(HybridDatabaseOptions)UseStoragePreset(CSharpDbStoragePreset)UseEmbeddedOpenMode(CSharpDbEmbeddedOpenMode)
Explicit DirectDatabaseOptions override Storage Preset. Explicit HybridDatabaseOptions override Embedded Open Mode. When EF Core is given an existing CSharpDbConnection, provider builder tuning is validated against that connection instead of mutating it.
For the full ADO.NET and EF Core tuning surface, see ADO.NET and EF storage tuning notes.
Migrations
For file-backed databases, the normal EF Core design-time workflow is supported.
dotnet ef migrations add InitialCreate
dotnet ef database update
dotnet ef migrations script
Database.Migrate() is supported for file-backed databases. EnsureCreated() is supported for file-backed and private in-memory databases. Migrations use the standard __EFMigrationsHistory table plus a simple __EFMigrationsLock row to serialize concurrent migration runs across processes.
Supported Surface
| Area | Supported | Notes |
|---|---|---|
| Embedded runtime provider | Yes | No daemon or remote transports |
| File-backed databases | Yes | Primary supported runtime and migration mode |
Private :memory: runtime | Yes | Requires an open CSharpDbConnection |
EnsureCreated() | Yes | File-backed and private in-memory |
Database.Migrate() | Yes | File-backed only |
dotnet ef migrations add | Yes | Use the app project with Microsoft.EntityFrameworkCore.Design |
dotnet ef database update | Yes | File-backed only |
dotnet ef migrations script | Yes | Non-idempotent scripts only |
| CRUD + change tracking | Yes | Includes affected-row concurrency checks |
| Integer identity propagation | Yes | Single-column integer primary keys |
| Basic LINQ/query subset | Yes | Where, ordering, pagination, scalar projections, First/Single, Any, Count, null checks, Contains, and simple navigation-loading joins |
| Supported CLR types | Yes | bool, integral types, enums, double, float, string, Guid, DateTime, DateTimeOffset, DateOnly, TimeOnly, byte[] |
Current Limitations
decimalrequires an explicit value converter.- Schemas are unsupported in runtime and migrations.
- Defaults, computed columns, check constraints, and rowversion are unsupported.
- Pooled connections are rejected by the EF Core provider.
- Named shared-memory databases (
:memory:<name>) are rejected. - Endpoint, daemon, and non-direct transports are rejected.
- Standalone foreign-key alteration migrations are unsupported.
- Idempotent migration scripts are unsupported in v1.
- Broad table-rebuild migration emulation is not implemented; unsupported operations fail explicitly.
DDL Surface
The migrations SQL generator currently supports CreateTable, DropTable, RenameTable, AddColumn, RenameColumn, DropColumn, CreateIndex, and DropIndex. Foreign keys are supported only when emitted inline during CreateTable, and only for the current single-column shape supported by the engine.