Skip to content

Commit

Permalink
Add Multiple App Databases docs
Browse files Browse the repository at this point in the history
  • Loading branch information
mythz committed Jul 24, 2023
1 parent 5ddf610 commit dead209
Show file tree
Hide file tree
Showing 3 changed files with 356 additions and 0 deletions.
111 changes: 111 additions & 0 deletions MyApp/_pages/ormlite/install-postgres-mysql-sqlserver.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
---
title: Install PostgreSQL, MySql and SQL Server with Docker
---

Installing developer tools has become frictionless in today's world of ubiquitous Docker adoption. First thing you'll
need to install is [Docker Desktop](https://www.docker.com/products/docker-desktop/) which will let you run each RDBMS
in a containerized Docker App.

After Docker is running, installing and running PostgreSQL and MySql can be done with a single command:

## Install and run PostgreSQL

:::copy
docker run --name postgres -e POSTGRES_PASSWORD=p@55wOrd -p 127.0.0.1:5432:5432 -d postgres
:::

## Install and run MySql

:::copy
docker run --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=p@55wOrd -d mysql:latest
:::

> Feel free to update commands to use your preferred strong password instead
## Install and run SQL Server

SQL Server requires more resources than the popular RDBMS's and as it doesn't have a native ARM Docker Image requires
a bit more configuration.

First you'll want to ensure you have at least **4GB RAM** available to containers from
the **Resources** Tab in Docker Settings you can open with `⌘,`

![](https://servicestack.net/img/posts/postgres-mysql-sqlserver-on-apple-silicon/docker-resources.png)

## Apple Silicon

Our MacBook Air's **24GB RAM** configuration defaulted to **7.9 GB**, but if you have a lower configuration you'll want
to ensure **4GB** is available to SQL Server.

If you're running on Apple Silicon you'll want to ensure **Use Virtualization Framework** and **VirtioFS** is checked
in the **General** tab which will allow SQL Server **AMD64** Image will run on Apple's new
[Virtualization framework](https://developer.apple.com/documentation/virtualization):

![](https://servicestack.net/img/posts/postgres-mysql-sqlserver-on-apple-silicon/docker-general.png)

After which you'll be able to install and run SQL Server with:

:::copy
docker run --platform=linux/amd64 --name mssql -e ACCEPT_EULA=1 -e MSSQL_SA_PASSWORD=p@55wOrd -p 1433:1433 -d mcr.microsoft.com/mssql/server:2022-latest
:::

You'll be able to check if all Docker containers are now running by clicking on the **Containers** tab in Docker Desktop:

![](https://servicestack.net/img/posts/postgres-mysql-sqlserver-on-apple-silicon/docker-containers.png)

## lazydocker

Another great alternative to Docker Desktop for managing Docker Containers is [lazydocker](https://github.com/jesseduffield/lazydocker)
which can be installed with:

### macOS

:::sh
brew install lazydocker
:::

### Chocolatey (Windows)

Using [Chocolatey](https://chocolatey.org) is an easy way to install on Windows:

:::sh
choco install lazydocker
:::

As lazydocker a Terminal UI it can be run everywhere where there's a Terminal, in local and remote terminals as well as
Rider and VS Code's built-in Terminal UIs where you can quickly perform Docker tasks without breaking your development
workflow:

[![](https://servicestack.net/img/posts/postgres-mysql-sqlserver-on-apple-silicon/lazydocker.png)](https://github.com/jesseduffield/lazydocker)

## DataGrip

Now we can see they're all running, lets connect to them. You could use the command line tools specific to each database
but my preference is to use [JetBrains DataGrip](https://www.jetbrains.com/datagrip/) which lets you connect and manage
any RDBMS from a single Desktop App, including many of the most popular NoSQL data stores.

## Connect to all Database connections

In **Database Explorer**, click on the `+` New Icon to add a new Data Source to **Microsoft SQL Server**, **MySql**
and **PostgreSQL** using the passwords used to run the Docker commands (e.g.`p@55wOrd`) and the default user names
for each RDBMS:

- SQL Server: `sa`
- MySQL: `root`
- PostgreSQL: `postgres`

After connecting to all databases you should end up with active connections to all empty databases:

[![](https://servicestack.net/img/posts/postgres-mysql-sqlserver-on-apple-silicon/datagrip-databases.png)](https://www.jetbrains.com/datagrip/)

Which you can open a **New > Query Console** or `⇧⌘L` to start executing generic queries against like `SELECT @@VERSION`
in SQL Server to display the version of SQL Server that's running:

[![](https://servicestack.net/img/posts/postgres-mysql-sqlserver-on-apple-silicon/datagrip-mssql-version.png)](https://www.jetbrains.com/datagrip/)

## Creating new Databases with DataGrip

To do anything interesting you'll need databases, which you can create with `New > Database` for SQL Server and
PostgreSQL or `New > Schema` in MySQL:

[![](https://servicestack.net/img/posts/postgres-mysql-sqlserver-on-apple-silicon/datagrip-test.png)](https://www.jetbrains.com/datagrip/)
237 changes: 237 additions & 0 deletions MyApp/_pages/ormlite/multi-database-app.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
---
title: Multiple App Databases
---

ServiceStack Apps have great support for multiple App Databases, for all it's [supported RDBMS](/ormlite/installation)
starting with the built-in [Database Admin UI](https://docs.servicestack.net/admin-ui-database) which lets you
browse and query an App's configured databases:

<div class="flex justify-center">
<lite-youtube class="w-full mx-4 my-4" width="560" height="315" videoid="NZkeyuc_prg" style="background-image: url('https://img.youtube.com/vi/NZkeyuc_prg/maxresdefault.jpg')"></lite-youtube>
</div>

You can easily try this out from a new database-enabled [vue-mjs](https://vue-mjs.web-templates.io) project template,
created with the `x` [dotnet tool](https://docs.servicestack.net/dotnet-tool):

:::sh
dotnet tool install --global x
:::

This will let you create any [ServiceStack Project Template](/start) with your preferred Project Name from the command-line, e.g:

:::sh
x new vue-mjs DatabaseTest
:::

Which creates a new .NET App that you can open with your preferred .NET IDE or text editor, e.g:

:::sh
code DatabaseTest/DatabaseTest
:::

By default the App is configured to use a local SQLite database, we can extend it to
[connect to different RDBMS's](/ormlite/install-postgres-mysql-sqlserver)
by adding the necessary **RDBMS** and `AdminDatabaseFeature` NuGet packages in `DatabaseTest.csproj`:

```xml
<PackageReference Include="ServiceStack.OrmLite.MySql" Version="6.*" />
<PackageReference Include="ServiceStack.OrmLite.PostgreSQL" Version="6.*" />
<PackageReference Include="ServiceStack.OrmLite.SqlServer.Data" Version="6.*" />
<PackageReference Include="ServiceStack.Server" Version="6.*" />
```

::: info TIP
New dependencies can be installed with VS Code's **Restore** popup or by explicitly running `dotnet restore`
:::

We can then register named connections for each of our databases by replacing the existing `Configure.Db.cs` with:

```csharp
public class ConfigureDb : IHostingStartup
{
public void Configure(IWebHostBuilder builder) => builder
.ConfigureServices((context,services) => {
var dbFactory = new OrmLiteConnectionFactory(
context.Configuration.GetConnectionString("DefaultConnection") ?? "App_Data/db.sqlite",
SqliteDialect.Provider);

dbFactory.RegisterConnection("postgres",
"Server=localhost;User Id=postgres;Password=p@55wOrd;Database=test;Pooling=true;MinPoolSize=0;MaxPoolSize=200",
PostgreSqlDialect.Provider);

dbFactory.RegisterConnection("mysql",
"Server=localhost;User Id=root;Password=p@55wOrd;Database=test;Pooling=true;MinPoolSize=0;MaxPoolSize=200",
MySqlDialect.Provider);

dbFactory.RegisterConnection("mssql",
"Server=localhost;User Id=sa;Password=p@55wOrd;Database=test;MultipleActiveResultSets=True;Encrypt=False;",
SqlServer2012Dialect.Provider);

services.AddSingleton<IDbConnectionFactory>(dbFactory);
})
.ConfigureAppHost(appHost => {
// Enable built-in Database Admin UI at /admin-ui/database
appHost.Plugins.Add(new AdminDatabaseFeature());
});
}
```

This will now let us access the [registered databases](https://docs.servicestack.net/ormlite/getting-started#multiple-database-connections)
in our APIs, but first lets populate the databases with some data.

When a new project is created it populates its default configured SQLite database with some test data, we can do the same
for the other registered database by duplicating the App's initial [DB migration](https://docs.servicestack.net/ormlite/db-migrations)
to a new DB `Migration1001.cs` with:

:::sh
sed "s/1000/1001/" ./Migrations/Migration1000.cs > ./Migrations/Migration1001.cs
:::

Then annotating it with a `[NamedConnection]` attribute for each of your registered database, e.g:

```csharp
[NamedConnection("mssql")]
[NamedConnection("mysql")]
[NamedConnection("postgres")]
public class Migration1001 : MigrationBase
{
//...
}
```

That can then be executed with:

:::sh
npm run migrate
:::

Where it will execute all new DB Migrations, in this case apply the same Migration to each configured database.

Now that our App's databases are all populated and ready to go, we can run it with:

:::sh
npm run dev
:::

Then view the built-in Admin Database UI at:

:::sh
https://localhost:5001/admin-ui/database
:::

and signing in with the Admin user created in `Configure.AuthRepository.cs`:

- `[email protected]`
- `p@55wOrd`

Where it displays all the App's configured database tables on its home page:

![](https://servicestack.net/img/posts/postgres-mysql-sqlserver-on-apple-silicon/admin-db-home.png)

Whose contents can be viewed by drilling down and clicking on each table:

![](https://servicestack.net/img/posts/postgres-mysql-sqlserver-on-apple-silicon/admin-db-mssql-bookings.png)

Which displays its rows using the [AutoQuery Grid Vue Component](https://docs.servicestack.net/vue/autoquerygrid) that
can be sorted and filtered as needed:

![](https://servicestack.net/img/posts/postgres-mysql-sqlserver-on-apple-silicon/admin-db-postgres-coupons.png)

## Named database connections

Named connections can be opened by its name from the registered `IDbConnectionFactory`:

```csharp
using var db = dbFactory.Open("postgres");
```

Inside a Service this can be resolved using `OpenDbConnection`:

```csharp
public class MyServices : Service
{
public object Any(GetPostgresBookings request)
{
using var db = OpenDbConnection("postgres");
return db.Select<Booking>();
}
}
```

The `[NamedConnection]` attribute can be used to configure Services `base.Db` connection with the named connection RDBMS, e.g:

```csharp
[NamedConnection("mysql")]
public class QueryMySqlBookings {}

public class BookingServices : Service
{
public object Any(QueryMySqlBookings request) => Db.Select<Reports>();
}
```

Or if using [AutoQuery](/autoquery/) it can be used to associate Data Models with the named connection:

```csharp
[NamedConnection("mssql")]
public class QuerySqlServerBookings : QueryDb<Booking> {}
```

Otherwise for other Services the `[ConnectionInfo]` attribute can be used to change the `base.Db` to use the registered
named connection for all APIs in a Service class, e.g:

```csharp
[ConnectionInfo(NamedConnection = "postgres")]
public class PostgresServices : Service
{
public object Any(GetPostgresBookings request)
{
return db.Select<Booking>();
}
}
```

## Vue .mjs project template features

Whilst you have the App running, check out its other high-productivity features:

### Create a multi-user Booking system with AutoQuery

The App's Bookings APIs are built using [AutoQuery CRUD](https://docs.servicestack.net/autoquery-crud), allowing for
rapid development of typed CRUD Services using only declarative POCO DTOs:

<div class="not-prose text-center">
<a class="text-xl text-indigo-600" href="https://localhost:5001/bookings-auto">https://localhost:5001/bookings-auto</a>
</div>
<div class="flex justify-center">
<lite-youtube class="w-full mx-4 my-4" width="560" height="315" videoid="rSFiikDjGos" style="background-image: url('https://img.youtube.com/vi/rSFiikDjGos/maxresdefault.jpg')"></lite-youtube>
</div>

In addition, all AutoQuery APIs benefit from the built-in [Locode's](https://docs.servicestack.net/locode/) Auto Management UI:

<div class="not-prose text-center">
<a class="text-xl text-indigo-600" href="https://localhost:5001/locode">https://localhost:5001/locode</a>
</div>

[![](https://servicestack.net/img/posts/postgres-mysql-sqlserver-on-apple-silicon/db-test-locode.png)](https://docs.servicestack.net/locode/)

<div class="flex justify-center">
<lite-youtube class="w-full mx-4 my-4" width="560" height="315" videoid="hkuO_DMFXmc" style="background-image: url('https://img.youtube.com/vi/hkuO_DMFXmc/maxresdefault.jpg')"></lite-youtube>
</div>

As well as end-to-end typed integrations with the most [popular programming languages](/service-reference) accessible
from the [code tab](https://docs.servicestack.net/api-explorer#code-tab) of the built-in
[API Explorer](https://docs.servicestack.net/api-explorer):

<div class="not-prose text-center">
<a class="text-xl text-indigo-600" href="https://localhost:5001/ui/QueryBookings?tab=code">https://localhost:5001/ui/QueryBookings?tab=code</a>
</div>

[![](https://servicestack.net/img/posts/postgres-mysql-sqlserver-on-apple-silicon/db-test-ui-code.png)](https://docs.servicestack.net/api-explorer)

<div class="flex justify-center">
<lite-youtube class="w-full mx-4 my-4" width="560" height="315" videoid="lUDlTMq9DHU" style="background-image: url('https://img.youtube.com/vi/lUDlTMq9DHU/maxresdefault.jpg')"></lite-youtube>
</div>

I hope this has been an informative post and highlighted some cool products and features, any questions or feedback
is welcome by commenting below.
8 changes: 8 additions & 0 deletions MyApp/_pages/ormlite/sidebar.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@
{
"text": "Litestream",
"link": "/ormlite/litestream"
},
{
"text": "Install Postgres, MySql & MSSQL",
"link": "/ormlite/install-postgres-mysql-sqlserver"
},
{
"text": "Multiple App Databases",
"link": "/ormlite/multi-database-app"
}
]
},
Expand Down

0 comments on commit dead209

Please sign in to comment.