Get up and running with SharpHSQL in just 5 minutes! This guide covers the essentials for both ADO.NET and Native API approaches.
- Installation
- ADO.NET Quick Start
- Native API Quick Start
- Connection Strings
- Basic CRUD Operations
- Working with Transactions
- Common Patterns
Install SharpHSQL via NuGet:
dotnet add package SharpHsqlOr using Package Manager Console:
Install-Package SharpHsqlThe ADO.NET provider is the recommended approach for most applications as it follows standard .NET database patterns.
using System.Data;
using System.Data.Hsql;// In-memory database
var connectionString = "Initial Catalog=.;User Id=sa;Pwd=";
// File-based database (persists to disk)
// var connectionString = "Initial Catalog=./mydb;User Id=sa;Pwd=";
using var connection = new SharpHsqlConnection(connectionString);
connection.Open();using var createCmd = connection.CreateCommand();
createCmd.CommandText = @"
CREATE TABLE Customers (
Id INT PRIMARY KEY,
Name VARCHAR(100),
Email VARCHAR(100),
Balance DECIMAL(10,2),
Active BIT,
CreatedDate DATE
)";
createCmd.ExecuteNonQuery();using var insertCmd = connection.CreateCommand();
insertCmd.CommandText = "INSERT INTO Customers VALUES (@id, @name, @email, @balance, @active, @created)";
// Add parameters
insertCmd.Parameters.Add(new SharpHsqlParameter("@id", DbType.Int32, 0,
ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, 1));
insertCmd.Parameters.Add(new SharpHsqlParameter("@name", DbType.String, 0,
ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, "John Smith"));
insertCmd.Parameters.Add(new SharpHsqlParameter("@email", DbType.String, 0,
ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, "john@example.com"));
insertCmd.Parameters.Add(new SharpHsqlParameter("@balance", DbType.Decimal, 0,
ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, 1500.50m));
insertCmd.Parameters.Add(new SharpHsqlParameter("@active", DbType.Boolean, 0,
ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, true));
insertCmd.Parameters.Add(new SharpHsqlParameter("@created", DbType.DateTime, 0,
ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, DateTime.Now));
insertCmd.ExecuteNonQuery();using var selectCmd = connection.CreateCommand();
selectCmd.CommandText = "SELECT * FROM Customers WHERE Active = TRUE";
using var reader = selectCmd.ExecuteReader();
while (reader.Read())
{
Console.WriteLine($"ID: {reader.GetInt32(0)}");
Console.WriteLine($"Name: {reader.GetString(1)}");
Console.WriteLine($"Email: {reader.GetString(2)}");
Console.WriteLine($"Balance: {reader.GetDecimal(3)}");
Console.WriteLine($"Active: {reader.GetBoolean(4)}");
Console.WriteLine($"Created: {reader.GetDateTime(5)}");
Console.WriteLine("---");
}The Native API provides direct access to SharpHSQL's internal database engine for advanced scenarios.
using SharpHsql;// In-memory database
var database = new Database(".");
// File-based database
// var database = new Database("./mydb");
var channel = database.Connect("sa", "");var sql = @"CREATE TABLE Products (
Id INT PRIMARY KEY,
Name VARCHAR(100),
Price DECIMAL(10,2),
Stock INT
)";
var result = database.Execute(sql, channel);
// Check for errors
if (result.Error != null && result.Error != string.Empty)
{
Console.WriteLine($"Error: {result.Error}");
}var insertSql = "INSERT INTO Products VALUES (1, 'Widget', 29.99, 100)";
database.Execute(insertSql, channel);
insertSql = "INSERT INTO Products VALUES (2, 'Gadget', 49.99, 50)";
database.Execute(insertSql, channel);var selectSql = "SELECT * FROM Products WHERE Stock > 0";
var result = database.Execute(selectSql, channel);
// Process results
var record = result.Root;
while (record != null)
{
var row = record.Data;
Console.WriteLine($"ID: {row[0]}, Name: {row[1]}, Price: {row[2]}, Stock: {row[3]}");
record = record.Next;
}database.Execute("DISCONNECT", channel);Data is stored in memory and lost when the application closes.
"Initial Catalog=.;User Id=sa;Pwd="Data persists to disk in the specified directory.
"Initial Catalog=./mydata;User Id=sa;Pwd="
"Initial Catalog=C:\\Data\\mydb;User Id=sa;Pwd="- Username:
sa(system administrator) - Password: (empty string)
// Simple insert
cmd.CommandText = "INSERT INTO Users VALUES (1, 'Alice', 'alice@example.com')";
cmd.ExecuteNonQuery();
// Insert with parameters (recommended)
cmd.CommandText = "INSERT INTO Users VALUES (@id, @name, @email)";
cmd.Parameters.Add(new SharpHsqlParameter("@id", DbType.Int32, 0,
ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, 2));
cmd.Parameters.Add(new SharpHsqlParameter("@name", DbType.String, 0,
ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, "Bob"));
cmd.Parameters.Add(new SharpHsqlParameter("@email", DbType.String, 0,
ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, "bob@example.com"));
cmd.ExecuteNonQuery();
// Insert from SELECT
cmd.CommandText = "INSERT INTO UserBackup SELECT * FROM Users WHERE Active = TRUE";
cmd.ExecuteNonQuery();// Simple select
cmd.CommandText = "SELECT * FROM Users";
using var reader = cmd.ExecuteReader();
// Select with WHERE
cmd.CommandText = "SELECT Name, Email FROM Users WHERE Id = @id";
cmd.Parameters.Add(new SharpHsqlParameter("@id", DbType.Int32, 0,
ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, 1));
// Select with JOIN
cmd.CommandText = @"
SELECT u.Name, o.OrderDate, o.Total
FROM Users u
INNER JOIN Orders o ON u.Id = o.UserId
WHERE o.Total > 100";
// Select with aggregate
cmd.CommandText = "SELECT COUNT(*) FROM Users";
int count = (int)cmd.ExecuteScalar();// Simple update
cmd.CommandText = "UPDATE Users SET Email = 'newemail@example.com' WHERE Id = 1";
int rowsAffected = cmd.ExecuteNonQuery();
// Update with parameters
cmd.CommandText = "UPDATE Users SET Name = @name, Email = @email WHERE Id = @id";
cmd.Parameters.Add(new SharpHsqlParameter("@name", DbType.String, 0,
ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, "Alice Updated"));
cmd.Parameters.Add(new SharpHsqlParameter("@email", DbType.String, 0,
ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, "alice.new@example.com"));
cmd.Parameters.Add(new SharpHsqlParameter("@id", DbType.Int32, 0,
ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, 1));
cmd.ExecuteNonQuery();
// Update multiple rows
cmd.CommandText = "UPDATE Products SET Stock = Stock + 10 WHERE Stock < 20";
cmd.ExecuteNonQuery();// Delete specific row
cmd.CommandText = "DELETE FROM Users WHERE Id = @id";
cmd.Parameters.Add(new SharpHsqlParameter("@id", DbType.Int32, 0,
ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, 1));
int deleted = cmd.ExecuteNonQuery();
// Delete with condition
cmd.CommandText = "DELETE FROM Users WHERE Active = FALSE";
cmd.ExecuteNonQuery();
// Delete all rows
cmd.CommandText = "DELETE FROM TempData";
cmd.ExecuteNonQuery();using var connection = new SharpHsqlConnection("Initial Catalog=.;User Id=sa;Pwd=");
connection.Open();
using var transaction = connection.BeginTransaction();
try
{
var cmd = connection.CreateCommand();
cmd.CommandText = "INSERT INTO Accounts VALUES (1, 1000)";
cmd.ExecuteNonQuery();
cmd.CommandText = "UPDATE Accounts SET Balance = Balance - 100 WHERE Id = 1";
cmd.ExecuteNonQuery();
// Commit if all succeeded
transaction.Commit();
}
catch (Exception ex)
{
// Rollback on error
transaction.Rollback();
Console.WriteLine($"Transaction failed: {ex.Message}");
throw;
}using var transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted);
// ... perform operations
transaction.Commit();var adapter = new SharpHsqlDataAdapter("SELECT * FROM Users", connection);
var dataSet = new DataSet();
adapter.Fill(dataSet);
// Bind to DataGridView, modify data, etc.
foreach (DataRow row in dataSet.Tables[0].Rows)
{
Console.WriteLine(row["Name"]);
}cmd.CommandText = "SELECT EXISTS('Users')";
bool exists = (bool)cmd.ExecuteScalar();
if (!exists)
{
cmd.CommandText = "CREATE TABLE Users (Id INT PRIMARY KEY, Name VARCHAR(50))";
cmd.ExecuteNonQuery();
}cmd.CommandText = "INSERT INTO Users VALUES (NULL, 'Auto ID User', 'auto@example.com')";
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT IDENTITY()";
int lastId = (int)cmd.ExecuteScalar();
Console.WriteLine($"Last inserted ID: {lastId}");using var transaction = connection.BeginTransaction();
try
{
var cmd = connection.CreateCommand();
cmd.CommandText = "INSERT INTO Users VALUES (@id, @name, @email)";
for (int i = 1; i <= 1000; i++)
{
cmd.Parameters.Clear();
cmd.Parameters.Add(new SharpHsqlParameter("@id", DbType.Int32, 0,
ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, i));
cmd.Parameters.Add(new SharpHsqlParameter("@name", DbType.String, 0,
ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, $"User{i}"));
cmd.Parameters.Add(new SharpHsqlParameter("@email", DbType.String, 0,
ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, $"user{i}@example.com"));
cmd.ExecuteNonQuery();
}
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}// For small lists, build the IN clause dynamically
var ids = new[] { 1, 2, 3, 4, 5 };
var inClause = string.Join(",", ids);
cmd.CommandText = $"SELECT * FROM Users WHERE Id IN ({inClause})";- Read the Technical Reference for complete SQL syntax documentation
- Explore the test suite for more examples
- Check out CHANGELOG.md for version history
- Use Parameters: Always use parameterized queries to prevent SQL injection
- Transactions: Wrap multiple operations in transactions for consistency
- Dispose Resources: Use
usingstatements to ensure proper cleanup - File Paths: Use absolute paths for file-based databases in production
- Error Handling: Always check
result.Errorwhen using the Native API - Performance: Create indexes on frequently queried columns
- Testing: Use in-memory databases (
.) for unit tests
// Ensure the database path exists for file-based databases
var dbPath = "./mydb";
if (!Directory.Exists(Path.GetDirectoryName(dbPath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(dbPath));
}// Check for errors in results
if (result.Error != null && !string.IsNullOrEmpty(result.Error))
{
throw new Exception($"SQL Error: {result.Error}");
}Need more help? Check the Technical Reference or open an issue on GitHub.