Sqlify 0.3.14

dotnet add package Sqlify --version 0.3.14                
NuGet\Install-Package Sqlify -Version 0.3.14                
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="Sqlify" Version="0.3.14" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Sqlify --version 0.3.14                
#r "nuget: Sqlify, 0.3.14"                
#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 Sqlify as a Cake Addin
#addin nuget:?package=Sqlify&version=0.3.14

// Install Sqlify as a Cake Tool
#tool nuget:?package=Sqlify&version=0.3.14                

Sqlify

Build status Nuget Package

Fluent SQL builder library.

  • Just start build SQL query from Sql or PgSql classes.
  • Use Sqlify.Dapper library allowing Sqlify 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, CAST, COALESCE, NULLIF 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 Books with columns: Id, AuthorId, Rating
public interface IBooks : ITable
{
    public Column<int> Id { get; }
    public Column<int> AuthorId { get; }
    public Column<double> Rating { get; }
}

// Create model for table Authors with columns: Id, Name
public interface IAuthors : ITable
{
    public Column<int> Id { get; }
    public Column<int> Name { get; }
}

var a = Sql.Table<IAuthors>("a");
var b = Sql.Table<IBooks>("b");

var selectQuery = Sql
    .Select(a.Id, Sql.Count().As("Count"))
    .From(a)
    .Join(b, b.AuthorId == a.Id)
    .Where(b.Rating > 2.0)
    .Having(Sql.Count() >= 3)
    .OrderByDesc(Sql.Count());

// SELECT a.Id, COUNT(*) AS Count
// FROM Authors a 
// JOIN Books b ON b.AuthorId = a.Id 
// WHERE b.Rating > @p1 
// HAVING COUNT(*) >= @p2 
// ORDER BY COUNT(*) DESC

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")]
    Column<int> Id { get; }

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

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

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

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

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

    [Column("qty")]
    Column<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
{
    Column<int> Id { get; }

    Column<int> Name { get; }

    Column<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
var b = Sql.Table<IBooksTable>("b");
var query = Sql
    .Select(b.Rating.Cast<int>("INTEGER"))
    .From(b);

// SELECT CAST(b.rating AS INTEGER) FROM books b
var b = Sql.Table<IBooksTable>("b");
var query = Sql
    .Select(Sql.Coalesce(b.Name, "n/a"))
    .From(b);

// SELECT COALESCE(b.name, @p1) FROM books b
var b = Sql.Table<IBooksTable>("b");
var query = Sql
    .Select(Sql.NullIf(b.Name, "n/a"))
    .From(b);

// SELECT NULLIF(b.name, @p1) FROM books b

up ↑

Computed column

Define a table orders with computed column total = qty * price:

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

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

    [Column("price")]
    Column<int> Price { get; }

    [Column("total")]
    Expression<int> Total => Qty * Price; // <- computed column
}
var o = Sql.Table<IOrder>("o");

var query = Sql
    .Select(o.Id, o.Total)
    .From(o);

// SELECT o.id, o.qty * o.price AS total FROM orders o

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 Sqlify:

Package Downloads
Sqlify.Dapper

Fluent SQL builder for Dapper

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
0.3.14 273 8/16/2023
0.3.13 705 9/6/2022
0.3.11 671 9/3/2022
0.3.6 419 6/14/2022
0.3.4 440 5/31/2022
0.3.2 697 5/1/2022