-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 18ca90a
Showing
80 changed files
with
3,945 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
name: .NET 6 and 7 CI | ||
|
||
on: [push] | ||
|
||
jobs: | ||
build: | ||
|
||
runs-on: ubuntu-latest | ||
strategy: | ||
matrix: | ||
dotnet: [ '6.0.x', '7.0.x' ] | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- name: Setup .NET SDK | ||
uses: actions/setup-dotnet@v3 | ||
with: | ||
dotnet-version: | | ||
3.1.x | ||
${{ matrix.dotnet }} | ||
- name: Check BOM | ||
run: | | ||
dotnet tool install -g BomSweeper.GlobalTool | ||
$HOME/.dotnet/tools/bomsweeper '**/*.cs' '**/*.csproj' '**/*.sln' | ||
- name: Build | ||
run: dotnet build --configuration Release | ||
- name: Install | ||
run: dotnet tool install -g dotnet-reportgenerator-globaltool | ||
- name: Test | ||
run: | | ||
rm -rf MsTestResults | ||
dotnet test --configuration Release --no-build --logger "console;verbosity=detailed" --collect:"XPlat Code Coverage" --results-directory MsTestResults | ||
reportgenerator -reports:MsTestResults/*/coverage.cobertura.xml -targetdir:Coverlet-html | ||
- name: Archive artifacts (code coverage) | ||
uses: actions/upload-artifact@v3 | ||
with: | ||
name: code-coverage-report-${{ matrix.dotnet }} | ||
path: Coverlet-html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/.vs/ | ||
/*/bin/ | ||
/*/obj/ | ||
/SqlBind/dcx/ | ||
/SqlBind.Test/TestResults/ | ||
/Coverlet-Html/ | ||
/SqlBind/html/ | ||
/SqlBind/Properties/ | ||
/SqlBind.Test/Properties/ | ||
*.csproj.user |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
Copyright (c) 2023 Maroontress Fast Software. All rights reserved. | ||
|
||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions are | ||
met: | ||
1. Redistributions of source code must retain the above copyright | ||
notice, this list of conditions and the following disclaimer. | ||
2. Redistributions in binary form must reproduce the above copyright | ||
notice, this list of conditions and the following disclaimer in the | ||
documentation and/or other materials provided with the | ||
distribution. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS *AS IS* AND | ||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS | ||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE | ||
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN | ||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,304 @@ | ||
# SqlBind | ||
|
||
SqlBind.CSharp is a C# class library that is a wrapper for SQLite. | ||
|
||
## How to create a table and insert rows | ||
|
||
Let's consider creating the Actors table as follows: | ||
|
||
> ### _Actors_ | ||
> | ||
> | <u>id</u> | name | | ||
> | ---: | :--- | | ||
> | 1 | Chloë Grace Moretz | | ||
> | 2 | Gary Carr | | ||
> | 3 | Jack Reynor | | ||
Create the following class to represent this table: | ||
|
||
```csharp | ||
[Table("Actors")] | ||
public record class Actor( | ||
[Column("id")][PrimaryKey][AutoIncrement] long Id, | ||
[Column("name")] string Name) | ||
{ | ||
} | ||
``` | ||
|
||
Each parameter in the constructor of the `Actor` class corresponds to each column in the Actors table in the same order. The type of each parameter must be either `long` or `string`. | ||
|
||
Note that you can implement the `Actor` class without a `record` class. However, the parameter names of the constructor must start with an _uppercase_ letter if you create a regular one according to the naming conventions of the `record` class. This is inconsistent with general naming conventions. Therefore, we recommend that you use `record` classes. | ||
|
||
The following code from the `Example` class uses the `Actor` class to create the Actors table and add three rows of data to the table: | ||
|
||
```csharp | ||
public sealed class Example | ||
{ | ||
private TransactionKit Kit { get; } = new TransactionKit( | ||
"example.db", | ||
m => Console.WriteLine(m())); | ||
|
||
public void CreateTableAndInsertRows() | ||
{ | ||
Kit.Execute(q => | ||
{ | ||
q.NewTables(typeof(Actor)); | ||
q.Insert(new Actor(0, "Chloë Grace Moretz")); | ||
q.Insert(new Actor(0, "Gary Carr")); | ||
q.Insert(new Actor(0, "Jack Reynor")); | ||
}); | ||
} | ||
... | ||
``` | ||
|
||
The `Kit` property has the `TransactionKit` instance, which uses the `example.db` file as a database backend and writes log messages to the console. The `Execute` method executes the queries that the lambda expression of its parameter performs atomically (as a single transaction). | ||
|
||
Note that calling the `Insert(object)` method with the `Actor` instance ignores its `Id` property, which is specified with the first parameter of the constructor of the `Actor` class, because it is qualified with the `AutoIncrement` attribute. | ||
|
||
The log messages that the `CreateTableAndInsertRows()` method prints to the console are as follows: | ||
|
||
```plaintext | ||
DROP TABLE IF EXISTS Actors | ||
CREATE TABLE Actors (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT) | ||
INSERT INTO Actors (name) VALUES ($name) | ||
($name, Chloë Grace Moretz) | ||
INSERT INTO Actors (name) VALUES ($name) | ||
($name, Gary Carr) | ||
INSERT INTO Actors (name) VALUES ($name) | ||
($name, Jack Reynor) | ||
``` | ||
|
||
The non-indented lines are actual SQL statements that were automatically generated and executed. | ||
|
||
## How to select a table and get rows | ||
|
||
Then run the `SelectAllRows()` method as follows: | ||
|
||
```csharp | ||
public sealed class Example | ||
{ | ||
... | ||
public void SelectAllRows() | ||
{ | ||
Kit.Execute(q => | ||
{ | ||
var all = q.SelectAll<Actor>(); | ||
foreach (var i in all) | ||
{ | ||
Console.WriteLine(i); | ||
} | ||
}); | ||
} | ||
... | ||
``` | ||
|
||
The `SelectAllRows()` method outputs: | ||
|
||
```plaintext | ||
SELECT id, name FROM Actors | ||
Actor { Id = 1, Name = Chloë Grace Moretz } | ||
Actor { Id = 2, Name = Gary Carr } | ||
Actor { Id = 3, Name = Jack Reynor } | ||
``` | ||
|
||
The first line is the log message that the `TransactionKit` instance prints. The `SelectAll<T>()` method generates this statement. | ||
|
||
The next three lines are the messages that the `WriteLine(object)` method outputs within the `foreach` block. | ||
|
||
## Inner join with two or more tables | ||
|
||
Consider the following Titles table: | ||
|
||
> ### _Titles_ | ||
> | ||
> | id | name | | ||
> | ---: | :--- | | ||
> | 1 | Peripheral | | ||
|
||
And the following Casts table: | ||
|
||
> ### _Casts_ | ||
> | ||
> | id | titleId | actorId | role | | ||
> | ---: | ---: | ---: | :--- | | ||
> | 1 | 1 | 1 | Flynne Fisher | | ||
> | 2 | 1 | 2 | Wilf Netherton | | ||
> | 3 | 1 | 3 | Burton Fisher | | ||
|
||
The classes that correspond to these tables are: | ||
|
||
```csharp | ||
[Table("Titles")] | ||
public record class Title( | ||
[Column("id")][PrimaryKey][AutoIncrement] long Id, | ||
[Column("name")] string Name) | ||
{ | ||
} | ||
|
||
[Table("Casts")] | ||
public record class Cast( | ||
[Column("id")][PrimaryKey][AutoIncrement] long Id, | ||
[Column("titleId")] long TitleId, | ||
[Column("actorId")] long ActorId, | ||
[Column("role")] string Role) | ||
{ | ||
} | ||
``` | ||
|
||
The following code creates the tables and inserts the rows: | ||
|
||
```csharp | ||
public sealed class Example | ||
{ | ||
... | ||
public void CreateTables() | ||
{ | ||
Kit.Execute(q => | ||
{ | ||
q.NewTables(typeof(Title)); | ||
q.NewTables(typeof(Actor)); | ||
q.NewTables(typeof(Cast)); | ||
var titleId = q.InsertAndGetRowId(new Title(0, "Peripheral")); | ||
var allCasts = new (string Name, string Role)[] | ||
{ | ||
("Chloë Grace Moretz", "Flynne Fisher"), | ||
("Gary Carr", "Wilf Netherton"), | ||
("Jack Reynor", "Burton Fisher"), | ||
}; | ||
foreach (var (name, role) in allCasts) | ||
{ | ||
var actorId = q.InsertAndGetRowId(new Actor(0, name)); | ||
q.Insert(new Cast(0, titleId, actorId, role)); | ||
} | ||
}); | ||
} | ||
... | ||
``` | ||
|
||
The log messages that the `CreateTables()` method prints to the console are as follows: | ||
|
||
``` | ||
DROP TABLE IF EXISTS Titles | ||
CREATE TABLE Titles (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT) | ||
DROP TABLE IF EXISTS Actors | ||
CREATE TABLE Actors (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT) | ||
DROP TABLE IF EXISTS Casts | ||
CREATE TABLE Casts (id INTEGER PRIMARY KEY AUTOINCREMENT, titleId INTEGER, actorId INTEGER, role TEXT) | ||
INSERT INTO Titles (name) VALUES ($name) | ||
($name, Peripheral) | ||
select last_insert_rowid() | ||
INSERT INTO Actors (name) VALUES ($name) | ||
($name, Chloë Grace Moretz) | ||
select last_insert_rowid() | ||
INSERT INTO Casts (titleId, actorId, role) VALUES ($titleId, $actorId, $role) | ||
($titleId, 1) | ||
($role, Flynne Fisher) | ||
($actorId, 1) | ||
INSERT INTO Actors (name) VALUES ($name) | ||
($name, Gary Carr) | ||
select last_insert_rowid() | ||
INSERT INTO Casts (titleId, actorId, role) VALUES ($titleId, $actorId, $role) | ||
($titleId, 1) | ||
($role, Wilf Netherton) | ||
($actorId, 2) | ||
INSERT INTO Actors (name) VALUES ($name) | ||
($name, Jack Reynor) | ||
select last_insert_rowid() | ||
INSERT INTO Casts (titleId, actorId, role) VALUES ($titleId, $actorId, $role) | ||
($titleId, 1) | ||
($role, Burton Fisher) | ||
($actorId, 3) | ||
``` | ||
|
||
Let's suppose that you would like to get a list of the names of the actors who performed in the specified title. To do this, use the APIs as follows: | ||
|
||
```csharp | ||
public sealed class Example | ||
{ | ||
... | ||
public void ListActorNames(string title) | ||
{ | ||
Kit.Execute(q => | ||
{ | ||
var map = new Dictionary<string, object> | ||
{ | ||
["$name"] = title, | ||
}; | ||
var all = q.SelectAllFrom<Actor>("a") | ||
.InnerJoin<Cast>("c", "a.id = c.actorId") | ||
.InnerJoin<Title>("t", "t.id = c.titleId") | ||
.Where("t.name = $name", map) | ||
.Execute(); | ||
foreach (var i in all) | ||
{ | ||
Console.WriteLine(i.Name); | ||
} | ||
}); | ||
} | ||
... | ||
|
||
``` | ||
|
||
Calling `ListActorNames("Peripheral");` results in the following output: | ||
|
||
``` | ||
SELECT a.id, a.name FROM Actors a INNER JOIN Casts c ON a.id = c.actorId INNER JOIN Titles t ON t.id = c.titleId WHERE t.name = $name | ||
($name, Peripheral) | ||
Chloë Grace Moretz | ||
Gary Carr | ||
Jack Reynor | ||
``` | ||
|
||
<!-- | ||
## Get started | ||
|
||
SqlBind.CSharp is available as | ||
[the ![NuGet-logo][nuget-logo] NuGet package][nuget-maroontress.sqlbind]. | ||
--> | ||
|
||
## API Reference | ||
|
||
- [Maroontress.SqlBind][apiref-maroontress.sqlbind] namespace | ||
|
||
## How to build | ||
|
||
### Requirements for build | ||
|
||
- Visual Studio 2022 (Version 17.5) | ||
or [.NET 7.0 SDK (SDK 7.0.203)][dotnet-sdk] | ||
|
||
### Build | ||
|
||
```plaintext | ||
git clone URL | ||
cd SqlBind.CSharp | ||
dotnet build | ||
``` | ||
|
||
### Get the test coverage report with Coverlet | ||
|
||
Install [ReportGenerator][report-generator] as follows: | ||
|
||
```plaintext | ||
dotnet tool install -g dotnet-reportgenerator-globaltool | ||
``` | ||
|
||
Run all tests and get the report in the file `Coverlet-html/index.html`: | ||
|
||
```plaintext | ||
rm -rf MsTestResults | ||
dotnet test --collect:"XPlat Code Coverage" --results-directory MsTestResults \ | ||
&& reportgenerator -reports:MsTestResults/*/coverage.cobertura.xml \ | ||
-targetdir:Coverlet-html | ||
``` | ||
[report-generator]: | ||
https://github.com/danielpalme/ReportGenerator | ||
[dotnet-sdk]: | ||
https://dotnet.microsoft.com/en-us/download | ||
[apiref-maroontress.sqlbind]: | ||
https://maroontress.github.io/SqlBind-CSharp/api/latest/html/Maroontress.SqlBind.html | ||
[nuget-maroontress.sqlbind]: | ||
https://www.nuget.org/packages/Maroontress.SqlBind/ | ||
[nuget-logo]: | ||
https://maroontress.github.io/images/NuGet-logo.png |
Oops, something went wrong.