alnkesq / DuckDbSharp

Bidirectional interoperability between DuckDB and .NET
GNU Affero General Public License v3.0
11 stars 1 forks source link
dotnet duckdb parquet sql

protobuf-net

DuckDbSharp

DuckDbSharp is a bidirectional interoperability layer between DuckDB and .NET.

Features

Notes:

Usage

Calling DuckDB from .NET (auto-generated types)

-- my_query.sql
SELECT
    42 AS column1,
    [1, 2, 3] AS column2,
    [{a: 1, b: 2}] as column3
foreach (var user in db.ExecuteQuery_my_query())
{
    // "user" has an auto-generated type with all the fields and sub-fields of the SQL query above.
}

See detailed instructions below.

Calling DuckDB from .NET (inline sql)

using var db = ThreadSafeTypedDuckDbConnection.CreateInMemory();
foreach (var user in db.Execute<User>("select * from user"))
{

}

You can also use value tuples (Execute<(string A, int B)>("select 'a', 42")), but keep in mind that only column order matters, since tuple member names are erased at runtime.

Calling .NET from DuckDB

[DuckDbFunction]
public static IEnumerable<User> GetUsers(string country) { /*...*/ }
SELECT * FROM GetUsers('US')

Getting started

Benchmarks

Time to read ~100,000 rows of Northwind customers. In all 4 cases, the final result is a List<Customer>. Library Mean Error StdDev Description
DuckDbSharp (this project) 145.4 ms 2.63 ms 2.46 ms SELECT * FROM customer
DuckDB.NET + Dapper 177.2 ms 2.88 ms 2.69 ms SELECT * FROM customer
Protobuf-net 131.3 ms 2.52 ms 2.81 ms Deserialize from MemoryStream of protos
Newtonsoft JSON 241.7 ms 2.93 ms 2.60 ms Deserialize from MemoryStream of JSON

Note: while protobuf-net is slightly faster, its use cases is very different (serialization/deserialization only, with no query support)

Advanced features

Customizing (de)serialization