Open-source project
dotnetcore/FreeSql avatar
dotnetcore/FreeSql

FreeSql: one .NET ORM from MySql to DuckDB, with AOT as the headline

.NET aot orm, VB.NET/C# orm, Mysql/PostgreSQL/SqlServer/Oracle orm, Sqlite/Firebird/Clickhouse/DuckDB orm, 达梦/金仓/虚谷/翰高/高斯 orm, 神通 orm, 南大通用 orm, 国产 orm, TDengine orm, QuestDB orm, MsAccess orm.

4,405 stars910 forksC#MIT

At a glance

What is it?
FreeSql is a MIT-licensed O/RM component for .NET that calls itself the first AOT ORM, supporting .NET Core 2.1+, .NET Framework 4.0+ and Xamarin across eighteen plus databases including the mainstream four, the analytics newcomers like DuckDB and ClickHouse, and a long list of Chinese domestic engines. CodeFirst migration, navigation properties, read/write splitting and table splitting are built in.
Who is it for?
Choose FreeSql when a .NET codebase must talk to many database engines from one API, especially mixes involving Chinese domestic databases or analytics stores like ClickHouse, DuckDB, TDengine and QuestDB that mainstream ORMs treat as afterthoughts, or when AOT compilation is a hard requirement. Prefer Entity Framework Core when you want the ecosystem default with its documentation depth, FreeSql even ships an efcore_to_freesql example for the migration path.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Eighteen engines, four runtimes, one headline claim

FreeSql's banner claim is being the first AOT ORM, and the support matrix around that claim is wide, .NET Core 2.1 and later, .NET Framework 4.0 and later, Xamarin, and AOT compilation. The database list runs from MySql, SqlServer, PostgreSQL and Oracle through Sqlite, Firebird, ClickHouse, DuckDB, TDengine, QuestDB and MsAccess, and continues into Chinese domestic engines, Dameng, Kingbase or Renmin Jincang, GBase from Nanda Tongyong, Xugu, Shentong, Hangao and Gauss. The project is bilingual by default, with the README in English and Chinese side by side, community support runs through QQ groups with one group listed as available and three as full, and the homepage sits at fresql.net. Development is steady, v3.5.311 on 2026-07-31, v3.5.310 on 2026-06-13 and v3.5.309 on 2026-04-04, with the last push on 2026-09-20.

CodeFirst migrations, DbFirst imports, and the layer between

Two directional workflows cover the schema question. CodeFirst supports data migration, letting the entity structure drive the database, and the quick start enables it with one builder flag, UseAutoSyncStructure(true), automatically synchronizing the entity structure to the database. DbFirst works the other way, importing entity classes from an existing database, or generating them with the documented generation tool. Between the two sits the mapping layer, with advanced type mapping such as PostgreSQL array types called out specifically, and expression functions with customizable analysis, meaning the translation of LINQ style expressions into SQL is extensible rather than fixed. The builder pattern defines the entry point, FreeSqlBuilder with UseConnectionString taking a DataType enum and the connection string, finishing with Build, with the documentation insisting the resulting IFreeSql be defined as a singleton.

Navigation properties in all three multiplicities

The query surface treats relationships as first class, with one-to-many and many-to-many navigation properties, include and lazy loading all supported:

csharp
//OneToOne、ManyToOne
fsql.Select<Tag>().Where(a => a.Parent.Parent.Name == "English").ToList();

//OneToMany
fsql.Select<Tag>().IncludeMany(a => a.Tags, then => then.Where(sub => sub.Name == "foo")).ToList();

//ManyToMany
fsql.Select<Song>()
  .IncludeMany(a => a.Tags, then => then.Where(sub => sub.Name == "foo"))
  .Where(s => s.Tags.Any(t => t.Name == "Chinese"))
  .ToList();

Beyond navigation, the expression functions stretch into array containment with new[] { 1, 2, 3 }.Contains(a.Id), date truncation through a.CreateTime.Date == DateTime.Today, random sampling with OrderBy(a => Guid.NewGuid()).Limit(10), and anonymous type projection with nested subqueries per row.

Three development modes over one core

The project explicitly asks you to pick a mode. Use FreeSql directly and keep the original usage, use FreeSql.DbContext for Repository plus UnitOfWork, or use FreeSql.BaseEntity for a simple mode built on base entity classes. The repository flavor adds declarative transactions, and the example is compact:

csharp
[Transactional]
public void Add() {
  var repo = ioc.GetService<BaseRepository<Tag>>();
  repo.DbContextOptions.EnableCascadeSave = true;

  var item = new Tag {
    Name = "testaddsublist",
    Tags = new[] {
      new Tag { Name = "sub1" },
      new Tag { Name = "sub2" }
    }
  };
  repo.Insert(item);
}

The Transactional attribute together with a UnitOfWorkManager provides multiple transaction propagation in ASP.NET Core, documented in issue 289, and cascade save is a switch on the DbContext options rather than per-call configuration.

Read/write splitting, table splitting, filters, two lockers

The operational feature cluster covers the shapes a growing application eventually needs. Read/write separation sends queries and commands to different servers. Splitting Table and Splitting Database shard the schema across tables and databases. Global filters apply conditions like soft deletes everywhere without repeating them, and the query examples show both a hard Where(a => a.IsDelete == 0) and conditional composition with WhereIf(keyword != null, ...) and WhereIf(role_id > 0, ...). Concurrency control offers both optimistic and pessimistic locking, an either-or choice most ORMs decline to provide together. AOP hooks, a repository layer, unit of work and raw ADO access each have their own wiki pages, so the escape hatches are documented rather than implied.

The benchmark table, read honestly

The performance section publishes a comparison against Dapper at 131072 queried entities per run, and the honest reading is that results are mixed. Dapper's entity query lands at 0.673 seconds and FreeSql's at 0.682, effectively even. FreeSql's ToList of tuples is the fastest single result at 0.421 seconds against Dapper's 0.455, while FreeSql's dynamic query is the slowest entry at 1.024 seconds versus Dapper's 0.685. That spread is exactly why the repository carries a benchmarker example project plus orm_vs and orm_vs_net40 comparison examples, so the numbers can be reproduced on your own hardware and your own workload shape rather than taken on faith. The published table is evidence the author took the comparison seriously, not a claim of blanket superiority.

A VB test suite and an EF Core escape hatch

The repository layout reveals the breadth behind the description. FreeSql.Tests.VB is a dedicated test project for the Visual Basic surface, matching the vbnet ORM claim in the repository description. The Providers directory holds the per engine implementations and Extensions the add-ons, with FreeSql.DbContext, FreeSql.Repository and FreeSql.All packaging the modes. The Examples directory is a catalogue of on ramps, efcore_to_freesql for migrations away from Entity Framework Core, base_entity and zero_entity for the simple modes, dbcontext_01, repository_01, aspnetcore_transaction, restful, a xamarin forms app and the benchmarker. Adopters named in the README include the Zhontai Admin.Core management system, a .NET 8 based CMS, an AIBPM workflow engine, and NetAdmin, a rapid development framework on C#12 and .NET 9.

Editorial conclusion

Choose FreeSql when a .NET codebase must talk to many database engines from one API, especially mixes involving Chinese domestic databases or analytics stores like ClickHouse, DuckDB, TDengine and QuestDB that mainstream ORMs treat as afterthoughts, or when AOT compilation is a hard requirement. Prefer Entity Framework Core when you want the ecosystem default with its documentation depth, FreeSql even ships an efcore_to_freesql example for the migration path. Before adopting, verify the provider package for your exact engine, pick one of the three development modes early since DbContext and BaseEntity change the code shape, and reproduce the benchmark examples yourself rather than trusting the published numbers, the project's own table shows mixed results.

Frequently asked questions

what is freesql?

FreeSql is a MIT-licensed O/RM component for .NET that bills itself as the first AOT ORM, supporting .NET Core 2.1+, .NET Framework 4.0+ and Xamarin. It covers more than eighteen databases, from MySql, SqlServer, PostgreSQL and Oracle to ClickHouse, DuckDB, TDengine, QuestDB, MsAccess and several Chinese domestic engines.

how to use freesql?

Install a provider package such as dotnet add package FreeSql.Provider.Sqlite, then build a singleton IFreeSql with FreeSqlBuilder, UseConnectionString with the DataType and connection string, and UseAutoSyncStructure for CodeFirst synchronization. Then pick one of the three modes, raw FreeSql, FreeSql.DbContext with Repository and UnitOfWork, or FreeSql.BaseEntity for a simple mode.

Which databases does FreeSql support?

The supported list includes MySql, SqlServer, PostgreSQL, Oracle, Sqlite, Firebird, ClickHouse, DuckDB, TDengine, QuestDB and MsAccess, plus Chinese domestic databases Dameng, Renmin Jincang, GBase from Nanda Tongyong, Xugu, Shentong, Hangao and Gauss, with the Providers directory holding the per engine implementations.

Official sources

  1. dotnetcore/FreeSql on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/dotnetcore-freesql.svg)](https://hysenlabs.com/projects/dotnetcore-freesql)