[GitHub-Aktion] [Code-Coverage-Bericht]
Verwenden Sie eines dieser Pakete:
Version | Paket | Beschreibung |
---|---|---|
sqlite-net-pcl | .NET-Standardbibliothek | |
sqlite-net-sqlcipher | Mit Verschlüsselungsunterstützung | |
sqlite-net-static | Spezielle Version, die P/Invokes für das von der Plattform bereitgestellte SQLite3 verwendet | |
sqlite-net-base | ohne SQLitePCLRaw-Bundle, sodass Sie Ihren eigenen Anbieter auswählen können |
SQLite-net ist eine Open-Source-Minimalbibliothek, die es .NET-, .NET Core- und Mono-Anwendungen ermöglicht, Daten in SQLite 3-Datenbanken zu speichern. Es wurde ursprünglich für die Verwendung mit Xamarin.iOS entwickelt, ist aber inzwischen auf die Funktionsfähigkeit auf allen Plattformen (Xamarin.*, .NET, UWP, Azure usw.) ausgelegt.
SQLite-net wurde als schnelle und praktische Datenbankschicht konzipiert. Sein Design folgt diesen Zielen :
Sehr einfach in bestehende Projekte zu integrieren und läuft auf allen .NET-Plattformen.
Dünner Wrapper über SQLite, der schnell und effizient ist. (Diese Bibliothek sollte nicht der Leistungsengpass Ihrer Abfragen sein.)
Sehr einfache Methoden zum sicheren Ausführen von CRUD-Operationen und -Abfragen (unter Verwendung von Parametern) und zum Abrufen der Ergebnisse dieser Abfragen auf stark typisierte Weise.
Funktioniert mit Ihrem Datenmodell, ohne dass Sie Ihre Klassen ändern müssen. (Enthält eine kleine reflexionsgesteuerte ORM-Schicht.)
Installieren Sie sqlite-net-pcl von NuGet.
Wichtig: Sie müssen das NuGet-Paket sowohl zu Ihrem .NET Standard-Bibliotheksprojekt als auch zu Ihrem plattformabhängigen App-Projekt hinzufügen.
SQLite-net ist alles in einer Datei enthalten (ich weiß, so cool, oder?) und lässt sich leicht zu Ihrem Projekt hinzufügen. Fügen Sie einfach SQLite.cs zu Ihrem Projekt hinzu und schon können Sie mit der Erstellung von Tabellen beginnen. Eine asynchrone Implementierung finden Sie in SQLiteAsync.cs.
Dies ist ein Open-Source-Projekt, das Beiträge/Vorschläge/Fehlerberichte von denjenigen willkommen heißt, die es verwenden. Wenn Sie Ideen zur Verbesserung der Bibliothek haben, posten Sie bitte ein Problem hier auf GitHub. Bitte schauen Sie sich die Anleitung zum Mitwirken an.
Bitte konsultieren Sie das Wiki für eine, ähm, vollständige Dokumentation.
Die Bibliothek enthält einfache Attribute, mit denen Sie den Aufbau von Tabellen steuern können. In einem einfachen Aktienprogramm könnten Sie Folgendes verwenden:
public class Stock
{
[ PrimaryKey , AutoIncrement ]
public int Id { get ; set ; }
public string Symbol { get ; set ; }
}
public class Valuation
{
[ PrimaryKey , AutoIncrement ]
public int Id { get ; set ; }
[ Indexed ]
public int StockId { get ; set ; }
public DateTime Time { get ; set ; }
public decimal Price { get ; set ; }
[ Ignore ]
public string IgnoreField { get ; set ; }
}
Sobald Sie die Objekte in Ihrem Modell definiert haben, haben Sie die Wahl zwischen APIs. Sie können die „synchrone API“ verwenden, bei der Aufrufe einzeln blockiert werden, oder Sie können die „asynchrone API“ verwenden, bei der Aufrufe nicht blockiert werden. Möglicherweise möchten Sie die asynchrone API für mobile Anwendungen verwenden, um die Reaktionsfähigkeit zu erhöhen.
Beide APIs werden in den beiden folgenden Abschnitten erläutert.
Sobald Sie Ihre Entität definiert haben, können Sie automatisch Tabellen in Ihrer Datenbank generieren, indem Sie CreateTable
aufrufen:
// Get an absolute path to the database file
var databasePath = Path . Combine ( Environment . GetFolderPath ( Environment . SpecialFolder . MyDocuments ) , " MyData.db " ) ;
var db = new SQLiteConnection ( databasePath ) ;
db . CreateTable < Stock > ( ) ;
db . CreateTable < Valuation > ( ) ;
Mit Insert
können Sie Zeilen in die Datenbank einfügen. Wenn die Tabelle einen automatisch inkrementierten Primärschlüssel enthält, steht Ihnen der Wert für diesen Schlüssel nach dem Einfügen zur Verfügung:
public static void AddStock ( SQLiteConnection db , string symbol ) {
var stock = new Stock ( ) {
Symbol = symbol
} ;
db . Insert ( stock ) ;
Console . WriteLine ( " {0} == {1} " , stock . Symbol , stock . Id ) ;
}
Ähnliche Methoden gibt es für Update
und Delete
.
Die einfachste Möglichkeit zur Datenabfrage ist die Verwendung der Table
-Methode. Dies kann Prädikate zur Einschränkung über WHERE-Klauseln und/oder das Hinzufügen von ORDER BY-Klauseln erfordern:
var query = db . Table < Stock > ( ) . Where ( v => v . Symbol . StartsWith ( " A " ) ) ;
foreach ( var stock in query )
Console . WriteLine ( " Stock: " + stock . Symbol ) ;
Sie können die Datenbank auch auf niedriger Ebene mit der Query
-Methode abfragen:
public static IEnumerable < Valuation > QueryValuations ( SQLiteConnection db , Stock stock ) {
return db . Query < Valuation > ( " select * from Valuation where StockId = ? " , stock . Id ) ;
}
Der generische Parameter der Query
-Methode gibt den Typ des Objekts an, das für jede Zeile erstellt werden soll. Dabei kann es sich um eine Ihrer Tabellenklassen oder eine beliebige andere Klasse handeln, deren öffentliche Eigenschaften mit der von der Abfrage zurückgegebenen Spalte übereinstimmen. Beispielsweise könnten wir die obige Abfrage wie folgt umschreiben:
public class Val
{
public decimal Money { get ; set ; }
public DateTime Date { get ; set ; }
}
public static IEnumerable < Val > QueryVals ( SQLiteConnection db , Stock stock ) {
return db . Query < Val > ( " select " Price " as " Money " , " Time " as " Date " from Valuation where StockId = ? " , stock . Id ) ;
}
Mithilfe der Execute
-Methode können Sie Aktualisierungen der Datenbank auf niedriger Ebene durchführen.
Die asynchrone Bibliothek verwendet die Task Parallel Library (TPL). Daher funktioniert die normale Verwendung von Task
-Objekten und den Schlüsselwörtern async
und await
für Sie.
Sobald Sie Ihre Entität definiert haben, können Sie automatisch Tabellen generieren, indem Sie CreateTableAsync
aufrufen:
// Get an absolute path to the database file
var databasePath = Path . Combine ( Environment . GetFolderPath ( Environment . SpecialFolder . MyDocuments ) , " MyData.db " ) ;
var db = new SQLiteAsyncConnection ( databasePath ) ;
await db . CreateTableAsync < Stock > ( ) ;
Console . WriteLine ( " Table created! " ) ;
Mit Insert
können Sie Zeilen in die Datenbank einfügen. Wenn die Tabelle einen automatisch inkrementierten Primärschlüssel enthält, steht Ihnen der Wert für diesen Schlüssel nach dem Einfügen zur Verfügung:
var stock = new Stock ( )
{
Symbol = " AAPL "
} ;
await db . InsertAsync ( stock ) ;
Console . WriteLine ( " Auto stock id: {0} " , stock . Id ) ;
Ähnliche Methoden gibt es für UpdateAsync
und DeleteAsync
.
Die Datenabfrage erfolgt am einfachsten mit der Table
-Methode. Dadurch wird eine AsyncTableQuery
Instanz zurückgegeben, woraufhin Sie Prädikate zur Einschränkung über WHERE-Klauseln und/oder das Hinzufügen von ORDER BY hinzufügen können. Die Datenbank wird erst dann physisch berührt, wenn eine der speziellen Abrufmethoden – ToListAsync
, FirstAsync
oder FirstOrDefaultAsync
– aufgerufen wird.
var query = db . Table < Stock > ( ) . Where ( s => s . Symbol . StartsWith ( " A " ) ) ;
var result = await query . ToListAsync ( ) ;
foreach ( var s in result )
Console . WriteLine ( " Stock: " + s . Symbol ) ;
Es stehen eine Reihe von Low-Level-Methoden zur Verfügung. Sie können die Datenbank auch direkt über die QueryAsync
-Methode abfragen. Über die von InsertAsync
usw. bereitgestellten Änderungsvorgänge hinaus können Sie ExecuteAsync
-Methoden ausgeben, um Datensätze direkt in der Datenbank zu ändern.
Eine weitere hilfreiche Methode ist ExecuteScalarAsync
. Dadurch können Sie ganz einfach einen Skalarwert aus der Datenbank zurückgeben:
var count = await db . ExecuteScalarAsync < int > ( " select count(*) from Stock " ) ;
Console . WriteLine ( string . Format ( " Found '{0}' stock items. " , count ) ) ;
sqlite-net wird normalerweise als leichter ORM (Object-Relational-Mapper) mit den Methoden CreateTable
und Table
verwendet. Sie können es jedoch auch als praktische Möglichkeit zum manuellen Ausführen von Abfragen verwenden.
Hier ist ein Beispiel für das Erstellen einer Tabelle, das Einfügen in diese (mit einem parametrisierten Befehl) und das Abfragen ohne Verwendung von ORM-Funktionen.
db . Execute ( " create table Stock(Symbol varchar(100) not null) " ) ;
db . Execute ( " insert into Stock(Symbol) values (?) " , " MSFT " ) ;
var stocks = db . Query < Stock > ( " select * from Stock " ) ;
Sie können eine verschlüsselte Datenbank verwenden, indem Sie das NuGet-Paket sqlite-net-sqlcipher verwenden.
Der Datenbankschlüssel wird im SqliteConnectionString
festgelegt, der an den Verbindungskonstruktor übergeben wird:
var options = new SQLiteConnectionString ( databasePath , true ,
key : " password " ) ;
var encryptedDb = new SQLiteAsyncConnection ( options ) ;
Wenn Sie Pragmas zur Steuerung der Verschlüsselung festlegen müssen, können Aktionen an die Verbindungszeichenfolge übergeben werden:
var options2 = new SQLiteConnectionString ( databasePath , true ,
key : " password " ,
preKeyAction : db => db . Execute ( " PRAGMA cipher_default_use_hmac = OFF; " ) ,
postKeyAction : db => db . Execute ( " PRAGMA kdf_iter = 128000; " ) ) ;
var encryptedDb2 = new SQLiteAsyncConnection ( options2 ) ;
Vielen Dank an die .NET-Community, die dieses Projekt angenommen hat, und vielen Dank an alle Mitwirkenden, die dazu beigetragen haben, dass dieses Projekt großartig wurde.
Vielen Dank auch an Tirza van Dijk (@tirzavdijk) für das tolle Logo!