Library / SDK
linq2db/linq2db avatar
linq2db/linq2db

linq2db: type-safe SQL for .NET, without change tracking

Linq to database provider.

3,331 stars481 forksC#MIT

At a glance

What is it?
linq2db sits between micro-ORMs and full ORMs: you write LINQ expressions that the C# compiler checks, and the library turns them into SQL for SQL Server, PostgreSQL, SQLite, Oracle, ClickHouse and others. The trade-off is that you manage entity state yourself.
Who is it for?
Adopt linq2db when you want compiler-checked queries, explicit SQL control and no change-tracking layer, and you are willing to write your own update and delete calls. Do not adopt it expecting Entity Framework-style tracked entities, migrations or lazy loading; the README states there is no change tracking, so that work is yours.
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

The gap linq2db fills between Dapper and Entity Framework

Dapper and PetaPoco have you write SQL strings and map rows back to objects. Entity Framework and LINQ to SQL give you LINQ and object tracking, but they own more of your runtime. linq2db takes the middle position deliberately. The README describes it as "one step above micro-ORMs like Dapper, Massive, or PetaPoco, in that you work with LINQ expressions, not with magic strings", and it says the library is "not as heavy as LINQ to SQL or Entity Framework" because "there is no change-tracking".

That sentence is the whole product decision. You get compile-time checking and refactoring support for queries, and you give up the unit-of-work that notices which properties you changed and emits an UPDATE for you. For teams whose queries are mostly reads with a few hand-written writes, that is a good trade. For teams that expect SaveChanges semantics, it is a rewrite of habits.

The audience is .NET and F# developers with POCOs already in place, working against one of the providers listed in the repository topics: SQL Server, PostgreSQL, MySQL, MariaDB, SQLite, Oracle, DB2, Firebird, Informix, SAP HANA, ClickHouse, Access and SQL CE. A single query API across that list is the practical reason to pick it over a provider-specific client.

How queries become SQL: DataConnection, DataContext and DataOptions

The entry points are DataConnection and DataContext, both constructed from a DataOptions instance. DataOptions is where provider selection and connection configuration live; the README's minimal example passes a SQL Server connection string straight into the constructor. The README also recommends creating one configured DataOptions instance and reusing it, for example by registering it in a DI container, rather than rebuilding it per call.

Above the connection, queries are LINQ expression trees. The compiler checks them, and the library translates them to the dialect of the configured provider. Beyond plain LINQ, the README lists explicit join syntax, CTE support, window and analytic functions, a merge API and bulk copy or insert. Those are the places where hand-written SQL usually creeps into a Dapper codebase; linq2db exposes them as API surface instead.

Extensibility runs the other direction too. The README describes the "ability to map custom SQL to static functions", which means a database function or expression you cannot express in LINQ can be declared once and called from query expressions. There is also a separate LinqToDB.EntityFrameworkCore package that adds linq2db functionality inside EF Core projects, and a LINQPad driver in the same repository. The repository also ships a LinqToDB.FSharp project, and the README points F# developers at Tests/FSharp.

Installing linq2db from NuGet and running a first query

The README links the NuGet profile for the packages rather than spelling out a package ID, so install the linq2db package from NuGet in the usual way for your project. The configuration examples below are copied from the README.

This is the minimal DataConnection setup, passing a SQL Server connection string through DataOptions:

cs
var db = new DataConnection(
  new DataOptions()
    .UseSqlServer(@"Server=.\;Database=Northwind;Trusted_Connection=True;"));

After that runs, db is a connection object bound to SQL Server. From it you write LINQ against your POCOs, and the library emits the SQL for the provider you selected.

Provider-specific settings are chained on the same DataOptions object. The README shows selecting a SQL Server version and client provider, then attaching an authentication token before the connection opens:

cs
var options = new DataOptions()
  .UseSqlServer(connectionString, SqlServerVersion.v2017, SqlServerProvider.MicrosoftDataSqlClient)
  .UseBeforeConnectionOpened(cn =>
    {
        ((SqlConnection)cn).AccessToken = accessToken;
    });

// pass configured options to data context constructor
var dc = new DataContext(options);

On .NET Framework, the README also documents a web.config or app.config path. Add a connection string with a providerName that matches an entry in ProviderName.cs, and the library can resolve it by name:

xml
<connectionStrings>
  <add name="Northwind" 
    connectionString = "Server=.\;Database=Northwind;Trusted_Connection=True;" 
    providerName     = "SqlServer" />
</connectionStrings>

For anything more dynamic, the README shows implementing ILinqToDBSettings with a class that yields IConnectionStringSettings instances, each carrying Name, ProviderName and ConnectionString. That interface is the hook for configuration that does not come from a file.

Working examples live in the examples repository and in Tests/Linq, which the README names as the place to find code samples.

The change-tracking gap is a real cost, not a footnote

The README is unusually direct: "There is no change-tracking, so you have to manage that yourself." Read that as a design boundary with consequences. There is no SaveChanges that diffs your object graph. If you load a row, set a property and expect an UPDATE, nothing happens until you write the update call yourself. The same applies to inserts and deletes on tracked entities. The README frames the upside as "more control and faster access to your data", and that is a fair description, but the control is manual.

The second boundary is provider variance. The repository topics list a wide set of engines, and the README links a separate bulk copy page, which is a hint that bulk operations are the area where behavior depends most on the target database. A query that translates cleanly on PostgreSQL may translate differently, or not at all, on Informix or Access. Version-specific behavior is explicit in the API: UseSqlServer takes a SqlServerVersion, which means the library expects you to tell it what it is talking to.

Third, this is not a migration tool. Nothing in the README describes schema generation or migrations, so a team coming from EF Core should not expect that layer to exist. You bring your own schema management.

linq2db compared with EF Core and Dapper

Against Dapper, the difference is where the SQL lives. Dapper keeps SQL as strings you write and pass to the connection; linq2db keeps it as expression trees the compiler checks. The README's phrase is "type-safe SQL", and the practical effect is that renaming a property breaks the build instead of failing at runtime. Dapper remains the lighter option when you want raw SQL and nothing between you and the driver; linq2db adds a translation layer you have to trust.

Against EF Core, the difference is what the framework owns. EF Core tracks entities, generates migrations and offers lazy loading. linq2db does none of those, per the README, and in exchange keeps a thinner abstraction. The two are not mutually exclusive: the repository ships linq2db.EntityFrameworkCore, which the README describes as adding linq2db functionality to EF Core projects. That is the migration path for a team that wants linq2db's query features, such as merge or bulk copy, inside an existing EF Core model rather than a full replacement.

Against LINQ to SQL, the README positions linq2db as the lighter of the two. LINQ to SQL is tied to SQL Server, while linq2db's provider list runs far wider, which is usually the deciding factor once a second database enters the picture.

Maintenance, releases and the MIT licence

The repository is not archived, and the last push was on 2026-09-23. Releases are frequent: v6.5.0 on 2026-09-11, v6.4.0 on 2026-08-07 and v6.3.0 on 2026-05-17. That cadence matters for upgrade planning, because a minor release every few months means a team pinning to a version will fall behind quickly, and the repository keeps a release notes page in its wiki for tracking what changed.

The licence is MIT, per the repository metadata and MIT-LICENSE.txt at the root. MIT is permissive: it allows commercial use, modification and redistribution with the licence text retained. That is a plain statement of what the licence grants, not legal advice; if your organization has rules about attribution or about dependencies in shipped binaries, read MIT-LICENSE.txt yourself.

Upgrade cost is mostly provider drift. Because DataOptions carries provider-specific options such as SqlServerVersion and SqlServerProvider, a version bump can change which client library is expected, and the README already shows MicrosoftDataSqlClient as a named choice. Budget time for re-running your query paths after a minor upgrade, particularly bulk copy and merge, which are the operations most likely to depend on server version.

What the README does not answer

Several things a new adopter would want are simply absent. There is no installation command in the README beyond the NuGet profile link, so the package ID and target framework matrix have to come from NuGet itself. There is no documented rollback or migration story for schema changes. There is no performance data in the README; the phrase "fastest LINQ database access library" appears as a claim without a benchmark, and the repository's linq2db.Benchmarks.slnf file suggests benchmarks exist to run, not to quote.

There is also no guidance on thread safety or connection lifetime beyond the recommendation to build DataOptions once and reuse it. Whether a DataConnection should be short-lived per operation or long-lived per scope is not stated in the README, and that is the first question most teams ask. Treat the tests directory as the reference: Tests/Linq is where the README sends you for examples, and it is the honest place to check behavior the prose does not cover.

Editorial conclusion

Adopt linq2db when you want compiler-checked queries, explicit SQL control and no change-tracking layer, and you are willing to write your own update and delete calls. Do not adopt it expecting Entity Framework-style tracked entities, migrations or lazy loading; the README states there is no change tracking, so that work is yours. Before committing, verify on your own machine that your provider is in the supported list in ProviderName.cs, that your database version is covered by the provider options you pass to DataOptions, and that bulk copy behaves as you expect on your target engine, since those paths differ per provider.

Frequently asked questions

What is LINQ and why is it used?

LINQ is the .NET query syntax that lets you write queries against objects in C#; linq2db uses it as the input to its SQL translation layer. The README describes the result as type-safe SQL, because the C# compiler checks the query and it can be refactored.

What does LINQ actually do?

In linq2db, a LINQ expression tree is translated into SQL for the configured provider and executed against your database. The README lists explicit join syntax, CTE support, window functions, a merge API and bulk copy as the query features built on top of it.

Is LINQ obsolete?

The README gives no sign of that for linq2db; the project released v6.5.0 on 2026-09-11 and the last push to the repository was on 2026-09-23. It also ships a LinqToDB.EntityFrameworkCore package and a LINQPad driver, so the LINQ surface is still being extended.

What are the disadvantages of LINQ?

In linq2db the README names the main one directly: there is no change tracking, so you manage updates yourself. It also notes the library is lighter than LINQ to SQL or Entity Framework, which means you give up the layers those frameworks provide.

How does linq2db compare with EF Core?

linq2db has no change tracking and a thinner abstraction, while EF Core tracks entities and generates migrations. The repository also ships linq2db.EntityFrameworkCore, which the README describes as adding linq2db functionality to EF Core projects rather than replacing them.

How does linq2db compare with Dapper performance-wise?

The README does not publish performance numbers for either library, so it gives no basis for a direct comparison. It does place linq2db one step above micro-ORMs like Dapper and PetaPoco because you work with LINQ expressions instead of magic strings.

Official sources

  1. Issues
  2. License: MIT
  3. linq2db/linq2db on GitHub
  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/linq2db-linq2db.svg)](https://hysenlabs.com/projects/linq2db-linq2db)