|
| 1 | +--- |
| 2 | +title: Configure storage provider - Microsoft SQL Server (MSSQL) |
| 3 | +description: Configure a Durable Functions app to use MSSQL |
| 4 | +author: davidmrdavid |
| 5 | +ms.topic: quickstart |
| 6 | +ms.date: 11/14/2022 |
| 7 | +ms.reviewer: azfuncdf |
| 8 | +--- |
| 9 | + |
| 10 | +# Configure Durable Functions with the Microsoft SQL Server (MSSQL) storage provider |
| 11 | + |
| 12 | +Durable Functions supports several [storage providers](durable-functions-storage-providers.md), also known as "backends", for storing orchestration and entity runtime state. By default, new projects are configured to use the [Azure Storage provider](durable-functions-storage-providers.md#azure-storage). In this article, we walk through how to configure a Durable Functions app to utilize the [MSSQL storage provider](durable-functions-storage-providers.md#mssql). |
| 13 | + |
| 14 | +> [!NOTE] |
| 15 | +> The MSSQL backend was designed to maximize application portability and control over your data. It uses [Microsoft SQL Server](https://www.microsoft.com/sql-server/) to persist all task hub state so that users get the benefits of modern, enterprise-grade DBMS infrastructure. To learn more about when to use the MSSQL storage provider, see the [storage providers](durable-functions-storage-providers.md) documentation. |
| 16 | +
|
| 17 | +## Note on data migration |
| 18 | + |
| 19 | +Migration of [Task Hub data](durable-functions-task-hubs.md) across storage providers is not currently supported. Function apps with existing runtime data will start with a fresh, empty task hub after switching to the MSSQL backend. Similarly, the task hub contents created with MSSQL cannot be preserved when switching to a different storage provider. |
| 20 | + |
| 21 | +## Prerequisites |
| 22 | + |
| 23 | +The following steps assume that you are starting with an existing Durable Functions app and are familiar with how to operate it. |
| 24 | + |
| 25 | +In particular, this quickstart assumes that you have already: |
| 26 | +1. Created an Azure Functions project on your local machine. |
| 27 | +2. Added Durable Functions to your project with an [orchestrator function](durable-functions-bindings.md#orchestration-trigger) and a [client function](durable-functions-bindings.md#orchestration-client) that triggers it. |
| 28 | +3. Configured the project for local debugging. |
| 29 | + |
| 30 | +If this is not the case, we suggest you start with one of the following articles, which provides detailed instructions on how to achieve all the requirements above: |
| 31 | + |
| 32 | +- [Create your first durable function - C#](durable-functions-create-first-csharp.md) |
| 33 | +- [Create your first durable function - JavaScript](quickstart-js-vscode.md) |
| 34 | +- [Create your first durable function - Python](quickstart-python-vscode.md) |
| 35 | +- [Create your first durable function - PowerShell](quickstart-powershell-vscode.md) |
| 36 | +- [Create your first durable function - Java](quickstart-java.md) |
| 37 | + |
| 38 | +## Add the Durable Task MSSQL extension (.NET only) |
| 39 | + |
| 40 | +> [!NOTE] |
| 41 | +> If your app uses [Extension Bundles](../functions-bindings-register.md#extension-bundles), you should ignore this section as Extension Bundles removes the need for manual Extension management. |
| 42 | +
|
| 43 | +You will need to install the latest version of the `Microsoft.DurableTask.SqlServer.AzureFunctions` [Extension on NuGet](https://www.nuget.org/packages/Microsoft.DurableTask.SqlServer.AzureFunctions) on your app. This usually means to include a reference to it in your `.csproj` file and building the project. |
| 44 | + |
| 45 | +You can install the Extension using the following [Azure Functions Core Tools CLI](../functions-run-local.md#install-the-azure-functions-core-tools) command |
| 46 | + |
| 47 | +```cmd |
| 48 | +func extensions install --package Microsoft.DurableTask.SqlServer.AzureFunctions --version <latestVersionOnNuget> |
| 49 | +``` |
| 50 | + |
| 51 | +For more information on installing Azure Functions Extensions via the Core Tools CLI, see [this guide](../functions-run-local.md#install-extensions). |
| 52 | + |
| 53 | +## Set up your Database |
| 54 | + |
| 55 | +> [!NOTE] |
| 56 | +> If you already have an MSSQL-compatible database, you may skip this section and its sub-section on setting up a Docker-based local database. |
| 57 | +
|
| 58 | +As the MSSQL backend is designed for portability, you have several options to set up your backing database. For example, you can set up an on-premises SQL Server instance, use a fully managed [Azure SQL DB](/azure/azure-sql/database/sql-database-paas-overview), or use any other SQL Server-compatible hosting option. |
| 59 | + |
| 60 | +You can also do local, offline development with [SQL Server Express](https://www.microsoft.com/sql-server/sql-server-downloads) on your local Windows machine or use [SQL Server Docker image](https://hub.docker.com/_/microsoft-mssql-server) running in a Docker container. For ease of setup, we will focus on the latter. |
| 61 | + |
| 62 | +### Set up your local Docker-based SQL Server |
| 63 | + |
| 64 | +To run these steps, you will need a [Docker](https://www.docker.com/products/docker-desktop/) installation on your local machine. Below are PowerShell commands that you can use to set up a local SQL Server database on Docker. Note that PowerShell can be installed on Windows, macOS, or Linux using the installation instructions [here](/powershell/scripting/install/installing-powershell). |
| 65 | + |
| 66 | +```powershell |
| 67 | +# primary parameters |
| 68 | +$pw = "yourStrong(!)Password" |
| 69 | +$edition = "Developer" |
| 70 | +$port = 1433 |
| 71 | +$tag = "2019-latest" |
| 72 | +$dbname = "DurableDB" |
| 73 | +$collation = "Latin1_General_100_BIN2_UTF8" |
| 74 | +
|
| 75 | +# pull the image from the Microsoft container registry |
| 76 | +docker pull mcr.microsoft.com/mssql/server:$tag |
| 77 | +
|
| 78 | +# run the image, providing some basic setup parameters |
| 79 | +docker run --name mssql-server -e 'ACCEPT_EULA=Y' -e "SA_PASSWORD=$pw" -e "MSSQL_PID=$edition" -p ${port}:1433 -d mcr.microsoft.com/mssql/server:$tag |
| 80 | +
|
| 81 | +# wait a few seconds for the container to start... |
| 82 | +
|
| 83 | +# create the database with strict binary collation |
| 84 | +docker exec -d mssql-server /opt/mssql-tools/bin/sqlcmd -S . -U sa -P "$pw" -Q "CREATE DATABASE [$dbname] COLLATE $collation" |
| 85 | +``` |
| 86 | + |
| 87 | +After running these commands, you should have a local SQL Server running on Docker and listening on port `1443`. If port `1443` conflicts with another service, you can re-run these commands after changing the variable `$port` to a different value. |
| 88 | + |
| 89 | +> [!NOTE] |
| 90 | +> To stop and delete a running container, you may use `docker stop <containerName>` and `docker rm <containerName>` respectively. You may use these commands to re-create your container, and to stop if after you're done with this quickstart. For more assistance, try `docker --help`. |
| 91 | +
|
| 92 | +To validate your database installation, you can query for your new SQL database using the following Docker command: |
| 93 | + |
| 94 | +```powershell |
| 95 | +docker exec -it mssql-server /opt/mssql-tools/bin/sqlcmd -S . -U sa -P "$pw" -Q "SELECT name FROM sys.databases" |
| 96 | +``` |
| 97 | + |
| 98 | +If the database setup completed successfully, you should see the name of your created database (for example, "DurableDB") in the command-line output. |
| 99 | + |
| 100 | +```bash |
| 101 | +name |
| 102 | + |
| 103 | +-------------------------------------------------------------- |
| 104 | +master |
| 105 | + |
| 106 | +tempdb |
| 107 | + |
| 108 | +model |
| 109 | + |
| 110 | +msdb |
| 111 | + |
| 112 | +DurableDB |
| 113 | + |
| 114 | +``` |
| 115 | + |
| 116 | +### Add your SQL connection string to local.settings.json |
| 117 | + |
| 118 | +The MSSQL backend needs a connection string to your database. How to obtain a connection string largely depends on your specific MSSQL Server provider. Please review the documentation of your specific provider for information on how to obtain a connection string. |
| 119 | + |
| 120 | +If you used Docker commands above without changing any parameters, your connection string should be: |
| 121 | + |
| 122 | +``` |
| 123 | +Server=localhost,1433;Database=DurableDB;User Id=sa;Password=yourStrong(!)Password; |
| 124 | +``` |
| 125 | + |
| 126 | +After obtaining your connection string, add it to a variable in `local.settings.json` so it can be used during local development. |
| 127 | + |
| 128 | +Below is an example `local.settings.json` assigning the default Docker-based SQL Server's connection string to the variable `SQLDB_Connection`. |
| 129 | + |
| 130 | + |
| 131 | +```json |
| 132 | +{ |
| 133 | + "IsEncrypted": false, |
| 134 | + "Values": { |
| 135 | + "AzureWebJobsStorage": "UseDevelopmentStorage=true", |
| 136 | + "SQLDB_Connection": "Server=localhost,1433;Database=DurableDB;User Id=sa;Password=yourStrong(!)Password;", |
| 137 | + "FUNCTIONS_WORKER_RUNTIME": "<dependent on your programming language>" |
| 138 | + } |
| 139 | +} |
| 140 | +``` |
| 141 | + |
| 142 | +> [!NOTE] |
| 143 | +> The value of `FUNCTIONS_WORKER_RUNTIME` is dependent on your programming language of choice. For more information, please see its [reference docs](../functions-app-settings.md#functions_worker_runtime). |
| 144 | +
|
| 145 | +### Update host.json |
| 146 | + |
| 147 | +Edit the storage provider section of the `host.json` file so it sets the `type` to `mssql`. We'll also specify the connection string variable name, `SQLDB_Connection`, under `connectionStringName`. We'll set `createDatabaseIfNotExists` to `true`; this setting creates a database named `DurableDB` if one does not already exists, with collation `Latin1_General_100_BIN2_UTF8`. |
| 148 | + |
| 149 | +```json |
| 150 | +{ |
| 151 | + "version": "2.0", |
| 152 | + "extensions": { |
| 153 | + "durableTask": { |
| 154 | + "storageProvider": { |
| 155 | + "type": "mssql", |
| 156 | + "connectionStringName": "SQLDB_Connection", |
| 157 | + "createDatabaseIfNotExists": true |
| 158 | + } |
| 159 | + } |
| 160 | + }, |
| 161 | + "logging": { |
| 162 | + "logLevel": { |
| 163 | + "DurableTask.SqlServer": "Warning", |
| 164 | + "DurableTask.Core": "Warning" |
| 165 | + } |
| 166 | + } |
| 167 | +} |
| 168 | +``` |
| 169 | + |
| 170 | +The snippet above is a fairly *minimal* `host.json` example. Later, you may want to consider [additional parameters](https://microsoft.github.io/durabletask-mssql/#/quickstart?id=hostjson-configuration). |
| 171 | + |
| 172 | +### Test locally |
| 173 | + |
| 174 | +Your app is now ready for local development: You can start the Function app to test it. One way to do this is to run `func host start` on your application's root and executing a simple orchestrator Function. |
| 175 | + |
| 176 | +While the function app is running, it updates runtime state in the configured SQL database. You can test this is working as expected using your SQL query interface. For example, in our docker-based local SQL server container, you can view the state of your orchestration instances with the following `docker` command: |
| 177 | + |
| 178 | +```bash |
| 179 | +docker exec -it mssql-server /opt/mssql-tools/bin/sqlcmd -S . -d $dbname -U sa -P "$pw" -Q "SELECT TOP 5 InstanceID, RuntimeStatus, CreatedTime, CompletedTime FROM dt.Instances" |
| 180 | +``` |
| 181 | + |
| 182 | +After running an orchestration, the previous query should return something like this: |
| 183 | + |
| 184 | +``` |
| 185 | +InstanceID RuntimeStatus CreatedTime CompletedTime |
| 186 | +------------------------------------ -------------------- ----------------------------- ---------------------------- |
| 187 | +9fe1ea9d109341ff923621c0e58f215c Completed 2022-11-16 21:42:39.1787277 2022-11-16 21:42:42.3993899 |
| 188 | +``` |
| 189 | + |
| 190 | +## Run your app on Azure |
| 191 | + |
| 192 | +To run your app in Azure, you will need a publicly accessible SQL Server instance. You can obtain one by creating an Azure SQL database. |
| 193 | + |
| 194 | +### Create an Azure SQL database |
| 195 | + |
| 196 | +> [!NOTE] |
| 197 | +> If you already have an Azure SQL database, or some other publicly accessible SQL Server you would like to use, you may skip to the next section. |
| 198 | +
|
| 199 | +You can follow [these](/azure/azure-sql/database/single-database-create-quickstart) instructions to create an Azure SQL database on the portal. When configuring the database, make sure to set the *Database collation* (under _Additional settings_) to `Latin1_General_100_BIN2_UTF8`. |
| 200 | + |
| 201 | +> [!NOTE] |
| 202 | +> Microsoft offers a [12-month free Azure subscription account]((https://azure.microsoft.com/free/) if you’re exploring Azure for the first time. |
| 203 | +
|
| 204 | +You may obtain your Azure SQL database's connection string by navigating to the database's blade in the Azure portal. Then, under Settings, select "Connection strings" and obtain the "ADO.NET" connection string. Make sure to provide your password in the template provided. |
| 205 | + |
| 206 | +Below is an example of the portal view for obtaining the Azure SQL connection string. |
| 207 | + |
| 208 | + |
| 209 | + |
| 210 | +In the Azure portal, the connection string will have the database's password removed: it is replaced with `{your_password}`. Replace that segment with the password you used to create the database earlier in this section. If you forgot your password, you may reset it by navigating to the database's blade in the Azure portal, selecting your *Server name* in the "Essentials" view, and clicking "Reset password" in the resulting page. Below are some guiding images. |
| 211 | + |
| 212 | + |
| 213 | + |
| 214 | + |
| 215 | + |
| 216 | + |
| 217 | +### Add connection string as an application setting |
| 218 | + |
| 219 | +You need to add your database's connection string as an application setting. To do this through the Azure portal, first go to your Azure Functions App view. Then go under "Configuration", select "New application setting", and there you can assign "SQLDB_Connection" to map to a publicly accessible connection string. Below are some guiding images. |
| 220 | + |
| 221 | + |
| 222 | + |
| 223 | + |
| 224 | +### Deploy |
| 225 | + |
| 226 | +You can now deploy your function app to Azure and run your tests or workload on it. To validate the MSSQL backend is correctly configured, you can query your database for Task Hub data. |
| 227 | + |
| 228 | +For example, with Azure SQL database you can query for your orchestration instances by navigating to your SQL database's blade, clicking Query Editor, authenticating, and then running the following query: |
| 229 | + |
| 230 | +```sql |
| 231 | +SELECT TOP 5 InstanceID, RuntimeStatus, CreatedTime, CompletedTime FROM dt.Instances |
| 232 | +``` |
| 233 | + |
| 234 | +After running a simple orchestrator, you should see at least one result, as shown below: |
| 235 | + |
| 236 | + |
| 237 | + |
| 238 | +For more information about the Durable Task MSSQL backend architecture, configuration, and workload behavior, see the [MSSQL storage provider documentation](https://microsoft.github.io/durabletask-mssql/). |
0 commit comments