Entity Framework Core provider for WitDatabase - a high-performance embedded database engine for .NET.
This package provides Entity Framework Core support for WitDatabase, allowing you to use familiar EF Core patterns like DbContext, DbSet, LINQ queries, and migrations.
dotnet add package OutWit.Database.EntityFrameworkusing Microsoft.EntityFrameworkCore;
using OutWit.Database.EntityFramework.Extensions;
// Define your DbContext
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
public DbSet<User> Users => Set<User>();
public DbSet<Order> Orders => Set<Order>();
}
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public DateTime CreatedAt { get; set; }
public List<Order> Orders { get; set; } = new();
}
public class Order
{
public int Id { get; set; }
public int UserId { get; set; }
public decimal TotalAmount { get; set; }
public DateTime OrderDate { get; set; }
public User User { get; set; }
}
// Configure and use
var options = new DbContextOptionsBuilder<AppDbContext>()
.UseWitDb("Data Source=myapp.witdb")
.Options;
using var context = new AppDbContext(options);var options = new DbContextOptionsBuilder<AppDbContext>()
.UseWitDbInMemory()
.Options;
using var context = new AppDbContext(options);
// Database exists only for the lifetime of the contextvar options = new DbContextOptionsBuilder<AppDbContext>()
.UseWitDb("Data Source=secure.witdb;Encryption=aes-gcm;Password=MySecurePassword")
.Options;// In Program.cs or Startup.cs
services.AddDbContext<AppDbContext>(options =>
options.UseWitDb(Configuration.GetConnectionString("DefaultConnection")));public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public int Version { get; set; } // Row version column
}
// In OnModelCreating
modelBuilder.Entity<Product>(entity =>
{
entity.Property(e => e.Version).IsWitRowVersion();
});public class Employee
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName { get; set; } // Computed column
}
// In OnModelCreating
modelBuilder.Entity<Employee>(entity =>
{
entity.Property(e => e.FullName)
.HasWitComputedColumnSql("FirstName || ' ' || LastName", stored: true);
});public class Document
{
public int Id { get; set; }
public string Content { get; set; }
public Guid ConcurrencyStamp { get; set; }
}
// In OnModelCreating
modelBuilder.Entity<Document>(entity =>
{
entity.Property(e => e.ConcurrencyStamp).IsConcurrencyToken();
});using OutWit.Database.EntityFramework.Query.Translators;
public class Profile
{
public int Id { get; set; }
public string Settings { get; set; } // JSON column
}
// In OnModelCreating
modelBuilder.Entity<Profile>(entity =>
{
entity.Property(e => e.Settings).HasJsonColumnType();
});
// Query JSON data using extension methods
var profiles = context.Profiles
.Where(p => p.Settings.JsonValue("$.theme") == "dark")
.ToList();
// Available JSON extension methods:
// - JsonValue(path) - Extract scalar value
// - JsonQuery(path) - Extract JSON fragment
// - JsonContains(value) - Check if JSON contains value
// - JsonLength() - Get array length
// - JsonType() - Get JSON value type
// - JsonValid() - Validate JSON stringpublic enum Status { Active, Inactive, Pending }
public class Task
{
public int Id { get; set; }
public Status Status { get; set; }
}
// In OnModelCreating - store enum as TEXT instead of INT
modelBuilder.Entity<Task>(entity =>
{
entity.Property(e => e.Status).HasEnumToStringConversion();
});High-performance bulk operations are available via extension methods:
using OutWit.Database.EntityFramework.Extensions;
// Bulk Insert - 3x faster than AddRange + SaveChanges
var users = Enumerable.Range(1, 10000)
.Select(i => new User { Name = $"User{i}", Email = $"user{i}@test.com" });
int inserted = await context.BulkInsertAsync(users);
// Bulk Update
var usersToUpdate = context.Users.AsNoTracking().Take(1000).ToList();
foreach (var user in usersToUpdate)
user.Status = "Active";
int updated = await context.BulkUpdateAsync(usersToUpdate);
// Bulk Delete
var usersToDelete = context.Users.Where(u => u.Status == "Inactive").ToList();
int deleted = await context.BulkDeleteAsync(usersToDelete);
// Bulk InsertOrUpdate (Upsert)
int affected = await context.BulkInsertOrUpdateAsync(mixedUsers);| C# Type | WitSQL Type | Notes |
|---|---|---|
bool |
BOOLEAN |
|
byte |
UTINYINT |
|
sbyte |
TINYINT |
|
short |
SMALLINT |
|
ushort |
USMALLINT |
|
int |
INT |
|
uint |
UINT |
|
long |
BIGINT |
|
ulong |
UBIGINT |
|
float |
FLOAT |
|
double |
DOUBLE |
|
decimal |
DECIMAL |
|
string |
TEXT |
|
byte[] |
BLOB |
|
DateTime |
DATETIME |
|
DateTimeOffset |
DATETIMEOFFSET |
|
DateOnly |
DATE |
|
TimeOnly |
TIME |
|
TimeSpan |
INTERVAL |
|
Guid |
GUID |
|
Enum |
INT |
Stored as integer by default |
| JSON | JSON |
Use HasJsonColumnType() |
The provider translates common LINQ methods to WitSQL:
ToUpper(),ToLower(),Trim(),TrimStart(),TrimEnd()Substring(),Replace(),Contains(),StartsWith(),EndsWith()IndexOf(),Length,Concat(),IsNullOrEmpty(),IsNullOrWhiteSpace()
Abs(),Ceiling(),Floor(),Round(),Truncate()Pow(),Sqrt(),Log(),Log10(),Exp()Sin(),Cos(),Tan(),Asin(),Acos(),Atan(),Atan2()Max(),Min(),Sign()
AddDays(),AddMonths(),AddYears()AddHours(),AddMinutes(),AddSeconds(),AddMilliseconds()Year,Month,Day,Hour,Minute,SecondDate,TimeOfDay,DayOfWeek,DayOfYearDateTime.Now,DateTime.UtcNow,DateTime.Today
JsonValue(),JsonQuery(),JsonContains()JsonLength(),JsonType(),JsonValid()
Guid.NewGuid()
All connection string options from OutWit.Database.AdoNet are supported:
| Option | Description | Example |
|---|---|---|
Data Source |
Database file path or :memory: |
Data Source=mydb.witdb |
Mode |
Connection mode | Mode=ReadOnly |
Encryption |
Encryption algorithm | Encryption=aes-gcm |
Password |
Encryption password | Password=secret |
Store |
Storage engine | Store=btree or Store=lsm |
- .NET 10.0
- Microsoft.EntityFrameworkCore.Relational 9.0+ or 10.0+
- OutWit.Database.AdoNet
OutWit.Database.Core- Core database engineOutWit.Database.AdoNet- ADO.NET provider
Licensed under the Apache License, Version 2.0. See LICENSE.
If you use OutWit.Database.EntityFramework in a product, a mention is appreciated (but not required), for example: "Powered by WitDatabase https://witdatabase.io/".
"WitDatabase" and the WitDatabase logo are used to identify the official project by Dmitry Ratner.
You may:
- refer to the project name in a factual way (e.g., "built with WitDatabase");
- use the name to indicate compatibility (e.g., "WitDatabase-compatible").
You may not:
- use "WitDatabase" as the name of a fork or a derived product in a way that implies it is the official project;
- use the WitDatabase logo to promote forks or derived products without permission.
- ROADMAP.md - Planned features