SqlDsl 0.2.10

There is a newer version of this package available.
See the version list below for details.
dotnet add package SqlDsl --version 0.2.10                
NuGet\Install-Package SqlDsl -Version 0.2.10                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SqlDsl" Version="0.2.10" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add SqlDsl --version 0.2.10                
#r "nuget: SqlDsl, 0.2.10"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install SqlDsl as a Cake Addin
#addin nuget:?package=SqlDsl&version=0.2.10

// Install SqlDsl as a Cake Tool
#tool nuget:?package=SqlDsl&version=0.2.10                

SqlDsl

Build status Nuget Package

Fluent SQL builder library.

  • Just start build SQL query from Sql or PgSql classes.
  • Use SqlDsl.Dapper library allowing SqlDsl and Dapper to be used together.

Features:

  • SELECT, DELETE, INSERT, UPDATE queries
  • WHERE, JOIN, ORDER BY, GROUP BY, HAVING BY clauses
  • LIKE, EXISTS, IN, BETWEEN predicates
  • COUNT, SUM, MAX, MIN, AVG functions
  • UNION queries
  • Multiple queries
  • Table and Column aliases
  • SQL injections free
  • Partial PostgreSQL dialect support
  • Strongly typed (checked at compile time)
  • GC friendly

Getting started

// Create model for table Users with columns: Id, Name
public interface IUsersTable : ITable
{
    ColumnExpression<int> Id { get; }
    ColumnExpression<string> Name { get; }
}

var u = Sql.Table<IUsersTable>();

// INSERT INTO Users (Id, Name) VALUES (@p1, @p2)
var insertQuery = Sql
    .Insert(u)
    .Values(u.Id, 1)
    .Values(u.Name, "Alex");

// SELECT * FRO Users
var selectQuery = Sql
    .Select()
    .From(b);

// UPDATE Users SET Name = @p1 WHERE Users.Id = @p2
var updateQuery = Sql
    .Update(u)
    .Set(u.Name, "John")
    .Where(u.Id == 1);

// DELETE FROM Users WHERE Users.Id = @p1
var deleteQuery = Sql
    .Delete(u)
    .Where(u.Id == 1);

Examples

Schema definition

As an example, consider the following database schema (authors and books tables with one-to-many relationship):

CREATE TABLE authors (
    id integer PRIMARY KEY,
    name varchar(64)
)

CREATE TABLE books (
    id integer PRIMARY KEY,
    name varchar(512),
    author_id integer REFERENCES authors (id), -- one-to-many relationship
    rating real,
    qty integer
)

For these tables create corresponding interfaces:

[Table("authors")]
public interface IAuthorsTable : ITable
{
    [Column("id")]
    ColumnExpression<int> Id { get; }

    [Column("name")]
    ColumnExpression<string> Name { get; }
}

[Table("books")]
public interface IBooksTable : ITable
{
    [Column("id")]
    ColumnExpression<int> Id { get; }

    [Column("name")]
    ColumnExpression<string> Name { get; }

    [Column("author_id")]
    ColumnExpression<int> AuthorId { get; }

    [Column("rating")]
    ColumnExpression<double> Rating { get; }

    [Column("qty")]
    ColumnExpression<int> Quantity { get; }
}

If the names of the columns in the database are the same as the names of the properties in models, then using TableAttribute and ColumnAttrubute are optional.

For example, for schema:

CREATE TABLE Authors (
    Id integer PRIMARY KEY,
    Name varchar(64),
    BooksCount integer
)

you can define table like:

public interface IAuthorsTable : ITable
{
    ColumnExpression<int> Id { get; }

    ColumnExpression<int> Name { get; }

    ColumnExpression<int> BooksCount { get; }
}

up ↑

Aliases

var b = Sql.Table<IBooksTable>();
var query = Sql
    .Select(b.Id, b.Name)
    .From(b);

// SELECT books.id, books.name FROM books
var b = Sql.Table<IBooksTable>("t"); // table alias
var query = Sql
    .Select(b.Id, b.Name)
    .From(b);

// SELECT t.id, t.name FROM books t
var b = Sql.Table<IBooksTable>("t");
var query = Sql
    .Select(b.Id, b.Name.As("author_name")) // column alias
    .From(b);

// SELECT t.id, t.name AS author_name FROM books t

up ↑

Functions

var b = Sql.Table<IBooksTable>();
var query = Sql
    .Select(Sql.Count())
    .From(b);

// SELECT COUNT(*) FROM books
var b = Sql.Table<IBooksTable>("b");
var query = Sql
    .Select(Sql.Avg(b.Rating))
    .From(b);

// SELECT AVG(b.rating) FROM books b

up ↑

DISTINCT

var a = Sql.Table<IAuthorsTable>("a");
var query = Sql
    .Select(a.Name)
    .Distinct()
    .From(a);

// SELECT DISTINCT a.name FROM authors a

up ↑

Predicates

var b = Sql.Table<IBooksTable>("b");
var query = Sql
    .Select()
    .From(b)
    .Where(b.Name.IsNull.And(b.Rating <= 0));

// SELECT * FROM books b WHERE b.name IS NULL AND b.rating <= @p1
var b = Sql.Table<IBooksTable>("b");
var query = Sql
    .Select()
    .From(b)
    .Where(
        b.Name.IsNull, 
        b.Rating <= 0
    );

// SELECT * FROM books b WHERE b.name IS NULL AND b.rating <= @p1

up ↑

LIKE predicate

var a = Sql.Table<IAuthorsTable>("a");
var query = Sql
    .Select()
    .From(a)
    .Where(a.Name.Like("A%")); // started with 'A'

// SELECT * FROM authors a WHERE a.name LIKE @p1

up ↑

IN predicate

var a = Sql.Table<IAuthorsTable>("a");
var query = Sql
    .Select()
    .From(a)
    .Where(a.Id.In(new[] {1, 2})); // where id==1 OR id==2

// SELECT * FROM authors a WHERE a.id IN @p1
var a = Sql.Table<IAuthorsTable>("a");
var b = Sql.Table<IBooksTable>("b");

var subQuery = Sql
    .Select(b.AuthorId)
    .From(b)
    .Where(b.Rating > 3);

var query = Sql
    .Select()
    .From(a)
    .Where(a.Id.In(subQuery)); // IN sub-query
                   
// SELECT * FROM authors a WHERE a.id IN (SELECT b.author_id FROM books b WHERE b.rating > @p1)");

up ↑

EXISTS predicate

var a = Sql.Table<IAuthorsTable>("a");
var b = Sql.Table<IBooksTable>("b");

var subQuery = Sql
    .Select()
    .From(b)
    .Where((a.Id == b.AuthorId).And(b.Rating > 3));

var query = Sql
    .Select()
    .From(a)
    .WhereExists(subQuery);

// SELECT * FROM authors a WHERE EXISTS (SELECT * FROM books b WHERE a.id = b.author_id AND b.rating > @p1

up ↑

BETWEEN predicate

var b = Sql.Table<IBooksTable>("b");
var query = Sql
    .Select()
    .From(b)
    .Where(b.Rating.Between(2, 4));

// SELECT * FROM books b WHERE b.rating BETWEEN @p1 AND @p2

up ↑

JOIN ON clause

var a = Sql.Table<IAuthorsTable>("a");
var b = Sql.Table<IBooksTable>("b");
var query = Sql
    .Select()
    .Join(b, a.Id == b.AuthorId) // also LEFT, RIGHT, FULL JOIN
    .From(a);

// SELECT * FROM authors a JOIN books b ON a.id = b.author_id

up ↑

ORDER BY clause

var b = Sql.Table<IBooksTable>("b");
var query = Sql
    .Select()
    .OrderByDesc(b.Rating)
    .From(b);

// SELECT * FROM books b ORDER BY b.rating DESC

up ↑

GROUP BY clause

var b = Sql.Table<IBooksTable>("b");
var query = Sql
    .Select(b.AuthorId, Sql.Count())
    .GroupBy(b.AuthorId)
    .From(b);

// SELECT b.author_id, COUNT(*) FROM books b GROUP BY b.author_id

up ↑

Multiple queries

var a = Sql.Table<IAuthorsTable>();
var b = Sql.Table<IBooksTable>();
MultipleQuery query = Sql
    .Multiple(
        Sql.Select().From(a),
        Sql.Select().From(b)
    );
    
// SELECT * FROM authors; SELECT * FROM books        

up ↑

HAVING clause

var b = Sql.Table<IBooksTable>("b");
var query = Sql
    .Select(b.AuthorId, Sql.Count())
    .GroupBy(b.AuthorId)
    .Having(Sql.Count() > 3)
    .From(b);

// SELECT b.author_id, COUNT(*) FROM books b GROUP BY b.author_id HAVING COUNT(*) > @p1

up ↑

DELETE query

var b = Sql.Table<IBooksTable>();
var query = Sql
    .Delete(b)
    .Where(b.Id == 1);

// DELETE FROM books WHERE books.id = @p1

up ↑

INSERT query

var a = Sql.Table<IAuthorsTable>();
var query = Sql
    .Insert(a)
    .Values(a.Id, 1)
    .Values(a.Name, "Adam");
                
// INSERT INTO authors (id, name) VALUES (@p1, @p2)

up ↑

UPDATE query

var b = Sql.Table<IBooksTable>();
var query = Sql
    .Update(b)
    .Set(b.Rating, b.Rating + 1)
    .Where(b.AuthorId == 1);

// UPDATE books SET rating = books.rating + @p1 WHERE books.author_id = @p2

up ↑

PostgreSQL OFFSET and LIMIT clauses

var a = Sql.Table<IAuthorsTable>("a");
PgSelectQuery query = PgSql
    .Select()
    .From(a)
    .OrderBy(a.Name)
    .Offset(5)
    .Limit(10)

// SELECT * FROM authors a ORDER BY a.name OFFSET @p1 LIMIT @p2

up ↑

PostgreSQL UPDATE RETURNING clause

var b = Sql.Table<IBooksTable>();
PgUpdateQuery query = PgSql
    .Update(b)
    .Set(b.Rating, b.Rating + 1)
    .Returning(b.Id, b.Rating);

// UPDATE books SET rating = books.rating + @p1 RETURNING books.id, books.rating

up ↑

PostgreSQL INSERT RETURNING clause

var b = Sql.Table<IBooksTable>();
PgInsertQuery query = PgSql
    .Insert(b)
    .Values(b.Name, "name")
    .Returning();

// INSERT INTO books (name) VALUES (@p1) RETURNING *

up ↑

PostgreSQL DELETE RETURNING clause

var b = Sql.Table<IBooksTable>();
PgInsertQuery query = PgSql
    .Delete(b)
    .Returning();

// DELETE FROM books RETURNING *

up ↑

PostgreSQL INSERT ON CONFLICT DO clause

var b = Sql.Table<IBooksTable>("b");
PgInsertQuery query = PgSql
    .Insert(b)
    .Values(b.Id, 1)
    .Values(b.Name, "foo bar")
    .Values(b.Quantity, 5)
    .OnConflict(
        PgConflict.Columns(b.Name),
        PgConflict
            .DoUpdate()
            .Set(b.Quantity, b.Quantity + 5)
    );

// INSERT INTO books AS b (id, name, qty) VALUES (@p1, @p2, @p3) 
// ON CONFLICT (b.name) 
// DO UPDATE SET qty = b.qty + @p4"

up ↑

PostgreSQL SELECT FOR clause

var b = Sql.Table<IBooksTable>("b");
PgSelectQuery query = PgSql
    .Select()
    .From(b)
    .Where(b.Id == 3)
    .For(PgLockMode.Update); // mode: UPDATE, NO KEY UPDATE, SHARE, KEY SHARE

// SELECT * FROM books b WHERE b.id = @p1 FOR UPDATE

up ↑

How to build

# build
dotnet build ./src

# running tests
dotnet test ./src

# pack
dotnet pack ./src -c=release
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 is compatible. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on SqlDsl:

Package Downloads
SqlDsl.Dapper

Fluent SQL builder for Dapper

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
0.3.1 881 12/19/2021 0.3.1 is deprecated.
0.2.12 267 12/15/2021
0.2.11 1,621 11/28/2021
0.2.10 1,766 11/26/2021
0.2.6 262 11/22/2021
0.2.5 499 11/22/2021
0.1.30 408 11/12/2021
0.1.25 541 9/15/2021
0.1.24 385 9/12/2021
0.1.22 390 9/11/2021
0.1.21 415 9/11/2021
0.1.18 629 9/10/2021
0.1.11 325 9/2/2021
0.1.4 593 8/29/2021
0.1.1 368 8/28/2021