Open-source project
sqlkata/querybuilder avatar
sqlkata/querybuilder

SqlKata Query Builder: a C# SQL builder for teams that want SQL without string concatenation

SQL query builder, written in c#, helps you build complex queries easily, supports SqlServer, MySql, PostgreSql, Oracle, Sqlite and Firebird

3,384 stars521 forksC#MIT

At a glance

What is it?
SqlKata is an MIT-licensed C# query builder that compiles a fluent object model into SQL for SqlServer, MySql, PostgreSql, Oracle, Sqlite and Firebird. It is a builder first and an execution layer second, which is the split that decides whether it fits your project.
Who is it for?
Adopt SqlKata if you write C# against one of the six supported engines and you want composable query objects plus a compiler you can inspect, rather than an ORM that owns your entity model. Skip it if your database is not on the supported list, since the README states that new compilers are not accepted and points you at writing your own.
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 last received commits 173 days ago.
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 problem SqlKata solves: dynamic SQL in C# without string concatenation

Any application that filters, sorts and paginates on user input eventually needs to assemble a SQL statement at runtime. The naive version is string concatenation with parameters bolted on, and it goes wrong in predictable ways: a WHERE clause that only appears when a filter is set, an ORDER BY that has to be whitelisted because it cannot be parameterised, a JOIN that is only needed for one report. SqlKata addresses that layer. You build a query as a C# object, and a compiler turns it into SQL text and bindings for a specific database.

The intended audience is the C# developer who is comfortable with SQL and does not want to give it up. The README describes the syntax as inspired by Laravel Query Builder and Knex, and the API reads like SQL: Query, Where, Join, OrderByDesc, Limit. It is not an object-relational mapper. There is no entity tracking, no change detection, no migration story. What you get is a structured way to describe a statement, and the README positions it as framework-agnostic, so nothing ties it to ASP.NET or to a particular DI container.

How SqlKata compiles a query: QueryFactory, SqlCompiler and the dialect split

The architecture visible in the README and the repository layout is a two-stage pipeline. Stage one is the query object: you call db.Query("Books").Where("Id", 145).Where("Lang", "en"), and SqlKata accumulates that as a tree of clauses rather than as text. Stage two is the compiler. The SqlCompiler instance is passed into the QueryFactory constructor, and it is the compiler that knows the dialect. That is why the same builder code can target SqlServer, MySql, PostgreSql, Oracle, Sqlite or Firebird: the clause tree is shared, the compilation is not.

The repository reflects this split physically. QueryBuilder/ holds the builder and the compilers, SqlKata.Execution/ holds the execution layer, and QueryBuilder.Tests/ holds the tests. The README states that QueryFactory comes from the SqlKata.Execution package, which means the core package builds SQL and the execution package runs it. The README says execution support uses Dapper. That is a meaningful boundary: if you only want compiled SQL strings to hand to your own data layer, you do not need the execution package at all.

One feature worth calling out because it is unusual for a builder: Include. The README example calls db.Query("Books").Include(db.Query("Authors")) and states that it assumes the Books table has an AuthorId column. The result is a nested Author object on each book, and the README shows the shape as JSON with the included property in place. That is a batched include rather than a per-row lookup, and it is the kind of thing ORMs usually own. Here it is a builder feature.

Installing SqlKata and running a first query

Installation is two NuGet packages. The README gives both commands, and marks the execution package as optional depending on whether you want SqlKata to run the query for you.

bash
dotnet add package SqlKata
dotnet add package SqlKata.Execution # (optional) If you want the execution support

After that you wire up a connection, a compiler and a factory. The README shows exactly this, with a placeholder connection string and the default SqlCompiler. QueryFactory is provided by the SqlKata.Execution package, so this snippet only compiles if you installed the second package.

cs
var connection = new SqlConnection("...");
var compiler = new SqlCompiler();
var db = new QueryFactory(connection, compiler);

From there the first real query is a filtered read. The README uses a Books table and a First() call that returns a single record matching both conditions.

cs
var introToSql = db.Query("Books").Where("Id", 145).Where("Lang", "en").First();

What you should see is one row from Books where Id is 145 and Lang is en. If you want to inspect the generated SQL before running anything, keep the compiler and builder without the execution package and compile the statement to text; the README does not document a named method for that, so check the QueryBuilder/ sources for the compiler entry point you need.

Where SqlKata stops: unsupported databases and the missing ORM features

The clearest limitation is stated by the project itself. The README FAQ asks why a given database is not supported, and the answer is that supporting every vendor is impossible, so the focus is on the major ones, with an invitation to create your own compiler. The next FAQ entry closes that door further: new compilers are not accepted, because it would add overhead for the contributors, and the preference is to improve the existing ones. So if you are on a database outside SqlServer, MySql, PostgreSql, Oracle, Sqlite and Firebird, you are writing and maintaining a compiler yourself, with no path to upstreaming it.

A second boundary is that SqlKata is not an ORM, and the README's own FAQ points at the distinction between a query builder and an ORM. There is no identity map, no lazy loading, no schema generation, no migrations. If your application is built around an entity graph and you expect the data layer to track changes and flush them, SqlKata is the wrong tool, and the Include feature will not compensate for that. It also means relationships beyond the AuthorId convention shown in the README are your responsibility; the README states the assumption for Include but does not document a general relationship mapping.

SqlKata compared with Dapper and with a full ORM

The comparison that matters for a C# team is against Dapper alone, because SqlKata.Execution is built on Dapper per the README. Plain Dapper maps rows to objects and leaves the SQL entirely to you: you write the string, you manage the parameters, and dynamic filtering means you assemble that string yourself. SqlKata replaces that assembly step with a clause tree and a compiler, so the dynamic parts become method calls and the dialect differences move into the compiler. The cost is one more abstraction between you and the SQL text, and you now depend on the compiler emitting what you expect.

Against a full ORM the difference is direction of control. An ORM starts from your classes and derives the schema and the queries. SqlKata starts from the query and never asks about your classes, which is why it can sit on top of an existing schema with hand-written table and column names. The trade-off is that you get no query generation from a model, no tracking, and no migration tooling. Teams that already have a database and a DBA, and that want the SQL to stay recognisable, tend to prefer this direction. Teams that want the model to be the source of truth do not.

Maintenance, releases and what the MIT licence means here

The repository is not archived, and the last push was on 2026-04-10. The release history is sparse and uneven: v3.0.0-beta landed on 2022-10-28, and v4.0.0 and v4.0.1 both landed on 2025-02-01. That pattern matters for upgrade planning. A major version bump from v3 to v4 arrived after a long gap, and the patch release followed the major on the same day, which suggests v4.0.0 was followed immediately by a fix. If you are on v3, treat the move to v4 as a planned migration with test coverage on your generated SQL, not as a routine patch.

Upgrade cost also depends on how much of the compiler surface you touch. If you use the default SqlCompiler and the documented builder methods, your exposure is the public API of the builder. If you wrote a custom compiler for an unsupported database, you own that work across major versions, and the README's position that new compilers are not accepted means there is no upstream compatibility guarantee to lean on. The project is MIT licensed, so you can fork, modify and redistribute it, including in closed-source products, provided you keep the licence and copyright notice. That is a statement about the licence text, not legal advice; have your own counsel review anything that matters to you.

Editorial conclusion

Adopt SqlKata if you write C# against one of the six supported engines and you want composable query objects plus a compiler you can inspect, rather than an ORM that owns your entity model. Skip it if your database is not on the supported list, since the README states that new compilers are not accepted and points you at writing your own. Before committing, verify two things in your own environment: that the SQL emitted by the compiler for your dialect matches what your DBA expects, and whether you need the SqlKata.Execution package at all, because the core SqlKata package only builds and compiles.

Frequently asked questions

What is SqlKata Query Builder?

It is a SQL query builder written in C# that helps you build complex queries and supports SqlServer, MySql, PostgreSql, Oracle, Sqlite and Firebird. The README describes it as secure and framework-agnostic, inspired by Laravel Query Builder and Knex.

What is the difference between a query builder and an ORM?

SqlKata builds and compiles SQL statements from a clause tree and does not map an entity model, track changes or generate a schema. An ORM starts from your classes and derives queries and persistence behaviour from them.

How do I use SqlKata in a C# project?

The README gives two commands: dotnet add package SqlKata, and dotnet add package SqlKata.Execution, which is marked optional and is the package that provides QueryFactory for execution support.

Can I use SqlKata with a database it does not support?

The README FAQ states that supporting all vendors is impossible and encourages you to create your own compiler, but a separate FAQ entry says new compilers are not accepted because they add overhead for contributors.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. sqlkata/querybuilder on GitHub
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/sqlkata-querybuilder.svg)](https://hysenlabs.com/projects/sqlkata-querybuilder)