Skip to content

Commit

Permalink
WIP: Document Microsoft.Data.Sqlite
Browse files Browse the repository at this point in the history
  • Loading branch information
bricelam committed Dec 11, 2019
1 parent a94eed5 commit 7d08579
Show file tree
Hide file tree
Showing 69 changed files with 2,772 additions and 12 deletions.
2 changes: 1 addition & 1 deletion .markdownlint.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"default": true,
"MD013": false,
"MD025": { "front_matter_title": "" },
"MD033": { "allowed_elements": ["sup", "sub", "nobe"] }
"MD033": { "allowed_elements": ["sup", "sub", "nobr", "span"] }
}
2 changes: 1 addition & 1 deletion entity-framework/docfx.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
"ms.author": "avickers",
"feedback_system": "GitHub",
"feedback_github_repo": "aspnet/EntityFramework.Docs",
"feedback_product_url": "https://github.com/aspnet/EntityFrameworkCore/issues/new",
"feedback_product_url": "https://github.com/aspnet/EntityFrameworkCore/issues/new/choose",
"uhfHeaderId": "MSDocsHeader-DotNet"
},
"fileMetadata": {
Expand Down
3 changes: 2 additions & 1 deletion entity-framework/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@
href: core/modeling/keyless-entity-types.md
- name: Alternating models with same DbContext
href: core/modeling/dynamic-model.md
- name: Spatial Data (GIS)
- name: Spatial Data
displayName: GIS
href: core/modeling/spatial.md
- name: Relational database modeling
items:
Expand Down
61 changes: 59 additions & 2 deletions msdata-sqlite/TOC.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,59 @@
- name: Index
href: index.md
- name: Microsoft.Data.Sqlite
href: index.md
- name: Connection Strings
href: connection-strings.md
- name: Data Types
href: data-types.md
- name: Parameters
href: parameters.md
- name: Database Errors
displayName: Busy, Locked, Retries, Timeouts
href: errors.md
- name: Transactions
href: transactions.md
- name: Batching
href: batching.md
- name: Metadata
href: metadata.md
- name: SQLite Features
items:
- name: In-Memory Databases
href: memory.md
- name: Encryption
href: encryption.md
- name: Online Backup
href: backup.md
- name: User-Defined Functions
displayName: UDFs
href: udfs.md
- name: Custom SQLite Versions
href: custom-sqlite.md
- name: Collation
href: collation.md
- name: BLOB I/O
displayName: Streams
href: blob-io.md
- name: Interoperability
href: interop.md
- name: Extensions
href: extensions.md
- name: Limitations
items:
- name: ADO.NET
href: limitations.md
- name: Async
href: async.md
- name: Bulk Insert
href: bulk-insert.md
- name: Entity Framework Core
href: /ef/core/providers/sqlite/limitations
- name: Dapper
href: dapper.md
- name: System.Data.SQLite
href: compare.md
- name: Xamarin
href: xamarin.md
- name: API Reference
href: /dotnet/api/?view=msdata-sqlite-3.0.0
- name: SQL Syntax (external)
href: https://www.sqlite.org/lang.html
15 changes: 15 additions & 0 deletions msdata-sqlite/async.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
title: Async Limitations - Microsoft.Data.Sqlite
author: bricelam
ms.date: 11/22/2019
---
# Async Limitations

SQLite doesn't support asynchronous I/O. Async ADO.NET methods will execute synchronously in Microsoft.Data.Sqlite. Avoid calling them.

Instead, use [write-ahead logging <span class="docon docon-navigate-external" aria-hidden="true" />](https://www.sqlite.org/wal.html) to improve performance and concurrency.

[!code-csharp[](../samples/msdata-sqlite/AsyncSample/Program.cs?name=snippet_WAL)]

> [!TIP]
> Write-ahead logging is enabled by default on databases created using [Entity Framework Core](/ef/core/).
12 changes: 12 additions & 0 deletions msdata-sqlite/backup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
title: Online Backup - Microsoft.Data.Sqlite
author: bricelam
ms.date: 11/22/2019
---
# Online Backup

SQLite can back up database files while the app is running. This functionality is available in Microsoft.Data.Sqlite as the [BackupDatabase](/dotnet/api/microsoft.data.sqlite.sqliteconnection.backupdatabase) method on SqliteConnection.

[!code-csharp[](../samples/msdata-sqlite/BackupSample/Program.cs?name=snippet_Backup)]

Currently, BackupDatabase will back up the database as quickly as possible blocking other connections from writing to the database. Issue [#13834](https://github.com/aspnet/EntityFrameworkCore/issues/13834) would provide an alternative API to back up the database in the background allowing other connections to interrupt the backup and write to the database. If you're interested, please provide feedback on the issue.
16 changes: 16 additions & 0 deletions msdata-sqlite/batching.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
title: Batching - Microsoft.Data.Sqlite
author: bricelam
ms.date: 11/22/2019
---
# Batching

SQLite doesn't natively support batching SQL statements together into a single command. But because there's no network involved, it wouldn't really help performance anyway. Microsoft.Data.Sqlite does however implements statement batching as a convenience to make it behave more like other ADO.NET providers.

When calling DbCommand.ExecuteReader(), statements are executed up to the first one that returns results. Calling DbDataReader.NextResult() continues executing statements until the next one that returns results or until it reaches the end of the batch. Calling DbDataReader.Dispose() or Close() will execute any remaining statements that haven't been consumed by NextResult(). If you don't dispose a data reader, the finalizer will try to execute the remaining statements, but any errors it encounters will be ignored. Because of this, it's very important to dispose DbDataReader objects when using batches.

[!code-csharp[](../samples/msdata-sqlite/BatchingSample/Program.cs?name=snippet_Batching)]

## See also

* [Bulk Insert](bulk-insert.md)
20 changes: 20 additions & 0 deletions msdata-sqlite/blob-io.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
title: BLOB I/O - Microsoft.Data.Sqlite
author: bricelam
ms.date: 11/22/2019
---
# BLOB I/O

You can reduce memory usage while reading and writing large objects by streaming the data into and out of the database. This can be especially useful when parsing or transforming the data.

Start by inserting a row as normal. Use the zeroblob() SQL function to allocate space in the database to hold the large object. The last_insert_rowid() function provides a convenient way to get its rowid.

[!code-csharp[](../samples/msdata-sqlite/StreamingSample/Program.cs?name=snippet_Insert)]

After inserting the row, open a stream to write the large object using [SqliteBlob](/dotnet/api/microsoft.data.sqlite.sqliteblob).

[!code-csharp[](../samples/msdata-sqlite/StreamingSample/Program.cs?name=snippet_Write)]

To stream the large object out of the database, you must select the rowid or one of its aliases as show here in addition to the large object's column. If you don't select the rowid, the entire object will be loaded into memory. The object returned by GetStream() will be a SqliteBlob when done correctly.

[!code-csharp[](../samples/msdata-sqlite/StreamingSample/Program.cs?name=snippet_Read)]
10 changes: 9 additions & 1 deletion msdata-sqlite/breadcrumb/toc.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
- name: Docs
tocHref: /
topicHref: /
topicHref: /
items:
- name: .NET
tocHref: /dotnet/
topicHref: /dotnet/index
items:
- name: Microsoft.Data.Sqlite
tocHref: /msdata-sqlite/
topicHref: /msdata-sqlite/index
13 changes: 13 additions & 0 deletions msdata-sqlite/bulk-insert.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
title: Bulk Insert - Microsoft.Data.Sqlite
author: bricelam
ms.date: 11/22/2019
---
# Bulk Insert

SQLite doesn't have any special way to bulk insert data. To get optimal performance when inserting or updating data, ensure that you do the following.

1. Use a transaction.
2. Reuse the same parameterized command. Subsequent executions will reuse the compilation of the first one.

[!code-csharp[](../samples/msdata-sqlite/BulkInsertSample/Program.cs?name=snippet_BulkInsert)]
37 changes: 37 additions & 0 deletions msdata-sqlite/collation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
title: Collation - Microsoft.Data.Sqlite
author: bricelam
ms.date: 12/06/2019
---
# Collation

Collating sequences are used by SQLite when comparing TEXT values to determine order and equality. You can specify which collation to use when creating columns or per-operation in SQL queries. SQLite includes three collating sequences by default.

| Collation | Description |
| --------- | ----------------------------------------- |
| RTRIM | Ignores trailing whitespace |
| NOCASE | Case-insensitive for ASCII characters A-Z |
| BINARY | Case-sensitive. Compares bytes directly |

## Custom collation

You can also define your own collating sequences or override the built-in ones using [CreateCollation()](/dotnet/api/microsoft.data.sqlite.sqliteconnection.createcollation). The following example shows overriding the NOCASE collation to support Unicode characters. The [full sample code](https://github.com/aspnet/EntityFramework.Docs/blob/master/samples/msdata-sqlite/CollationSample/Program.cs) is available on GitHub.

[!code-csharp[](../samples/msdata-sqlite/CollationSample/Program.cs?name=snippet_Collation)]

## Like operator

The LIKE operator in SQLite doesn't honor collations. The default implementation has the same semantics as the NOCASE collation. It's only case-insensitive for the ASCII characters A through Z.

You can easily make the LIKE operator case-sensitive by using the following pragma statement.

```sql
PRAGMA case_sensitive_like = 0
```

See [User-Defined Functions](udfs.md) for details on overriding the implementation of the LIKE operator.

## See also

* [User-Defined Functions](udfs.md)
* [SQL Syntax <span class="docon docon-navigate-external" aria-hidden="true" />](https://www.sqlite.org/lang.html)
76 changes: 76 additions & 0 deletions msdata-sqlite/compare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
title: Comparison to System.Data.SQLite - Microsoft.Data.Sqlite
author: bricelam
ms.date: 12/09/2019
---
# Comparison to System.Data.SQLite

In 2005, Robert Simpson created System.Data.SQLite, a SQLite provider for ADO.NET 2.0. In 2010, the SQLite team took over maintenance and development of the project. It's also worth noting that the Mono team forked the code in 2007 as Mono.Data.Sqlite. System.Data.SQLite has a long history and has evolved into a stable and full-featured ADO.NET provider complete with Visual Studio tooling. New releases continue to ship assemblies compatible with every version of .NET Framework back to version 2.0 and even .NET Compact Framework 3.5.

The first version of .NET Core (released in 2016) was a single, lightweight, modern, and cross-platform implementation of .NET. Obsolete APIs and APIs with more modern alternatives were intentionally removed. ADO.NET didn't include any of the DataSet APIs (including DataTable and DataAdapter).

The Entity Framework team was somewhat familiar with the System.Data.SQLite codebase. Brice Lambson, a member of the EF team, had previously helped the SQLite team add support for Entity Framework versions 5 and 6. Brice was also experimenting with his own implementation of a SQLite ADO.NET provider around the same time that .NET Core was being planned. After a long discussion, the Entity Framework team decided to create Microsoft.Data.Sqlite based on Brice's prototype. This would allow them to create a new lightweight and modern implementation that would align with the goals of .NET Core.

As an example of what we mean by more modern, here is code to create a [user-defined function](udfs.md) in both System.Data.SQLite and Microsoft.Data.Sqlite.

```csharp
// System.Data.SQLite
connection.BindFunction(
new SQLiteFunctionAttribute("ceiling", 1, FunctionType.Scalar),
(Func<object[], object>)((object[] args) => Math.Ceiling((double)((object[])args[1])[0])),
null);

// Microsoft.Data.Sqlite
connection.CreateFunction(
"ceiling",
(double arg) => Math.Ceiling(arg));
```

In 2017, .NET Core 2.0 experienced a change in strategy. It was decided that compatibility with .NET Framework was vital to the success of .NET Core. Many of the removed APIs, including the DataSet APIs, were added back. Like it did for many others, this unblocked System.Data.SQLite allowing it to also be ported to .NET Core. The original goal of Microsoft.Data.Sqlite to be lightweight and modern, however, still remains. See [ADO.NET Limitations](limitations.md) for details about ADO.NET APIs not implemented by Microsoft.Data.Sqlite.

When new features are added to Microsoft.Data.Sqlite, the design of System.Data.SQLite is taken into account. We try to, when possible, minimize changes between the two to ease transitioning between them.

## Data types

The biggest difference between Microsoft.Data.Sqlite and System.Data.SQLite is how data types are handled. As described in [Data Types](data-types.md), Microsoft.Data.Sqlite doesn't try to hide the underlying quirkiness of SQLite, which allows any arbitrary string to be specified as the column type, and only has four primitive types: INTEGER, REAL, TEXT, and BLOB.

System.Data.SQLite applies additional semantics to column types mapping them directly to .NET types. This gives the provider a more strongly-typed feel, but it has some rough edges. For example, they had to introduce a new SQL statement (TYPES) to specify the column types of expressions in SELECT statements.

## Connection strings

Microsoft.Data.Sqlite has a lot fewer [connection string](connection-strings.md) keywords. The following table shows alternatives that can be used instead.

| Keyword | Alternative |
| ---------------- | --------------------------------------------------- |
| Cache Size | Send `PRAGMA cache_size = <pages>` |
| Default Timeout | Use the DefaultTimeout property on SqliteConnection |
| FailIfMissing | Use `Mode=ReadWrite` |
| FullUri | Use the Data Source keyword |
| Journal Mode | Send `PRAGMA journal_mode = <mode>` |
| Legacy Format | Send `PRAGMA legacy_file_format = 1` |
| Max Page Count | Send `PRAGMA max_page_count = <pages>` |
| Page Size | Send `PRAGMA page_size = <bytes>` |
| Read Only | Use `Mode=ReadOnly` |
| Synchronous | Send `PRAGMA synchronous = <mode>` |
| Uri | Use the Data Source keyword |
| UseUTF16Encoding | Send `PRAGMA encoding = 'UTF-16'` |

## Authorization

Microsoft.Data.Sqlite doesn't have any API exposing SQLite's authorization callback. Use issue [#13835](https://github.com/aspnet/EntityFrameworkCore/issues/13835) to provide feedback about this feature.

## Data change notifications

Microsoft.Data.Sqlite doesn't have any API exposing SQLite's data change notifications. Use issue [#13827](https://github.com/aspnet/EntityFrameworkCore/issues/13827) to provide feedback about this feature.

## Virtual table modules

Microsoft.Data.Sqlite doesn't have any API for creating virtual table modules. Use issue [#13823](https://github.com/aspnet/EntityFrameworkCore/issues/13823) to provide feedback about this feature.

## See also

* [Data Types](data-types.md)
* [Connection Strings](connection-strings.md)
* [Encryption](encryption.md)
* [ADO.NET Limitations](limitations.md)
* [Dapper Limitations](dapper.md)
Loading

0 comments on commit 7d08579

Please sign in to comment.