Skip to content

Commit

Permalink
(#102) Database: use EFCore to initialize a database
Browse files Browse the repository at this point in the history
  • Loading branch information
ForNeVeR committed Sep 26, 2021
1 parent 253669f commit 2ca51af
Show file tree
Hide file tree
Showing 12 changed files with 228 additions and 4 deletions.
12 changes: 12 additions & 0 deletions .config/dotnet-tools.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "5.0.10",
"commands": [
"dotnet-ef"
]
}
}
}
23 changes: 23 additions & 0 deletions Emulsion.Database/Emulsion.Database.fsproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<Compile Include="Models.fs" />
<Compile Include="EmulsionDbContext.fs" />
<Compile Include="Migrations\*.fs" />
<Compile Include="Initializer.fs" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="EntityFrameworkCore.FSharp" Version="5.0.3-beta006" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.10">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.10" />
</ItemGroup>

</Project>
20 changes: 20 additions & 0 deletions Emulsion.Database/EmulsionDbContext.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace Emulsion.Database

open Emulsion.Database.Models
open Microsoft.EntityFrameworkCore
open Microsoft.EntityFrameworkCore.Design

type EmulsionDbContext(dataSource: string) =
inherit DbContext()

[<DefaultValue>] val mutable telegramContents: DbSet<TelegramContent>
member this.TelegramContents with get() = this.telegramContents and set v = this.telegramContents <- v

override _.OnConfiguring options =
options.UseSqlite($"Data Source={dataSource};") |> ignore

/// This type is used by the EFCore infrastructure when creating a new migration.
type EmulsionDbContextDesignFactory() =
interface IDesignTimeDbContextFactory<EmulsionDbContext> with
member this.CreateDbContext _ =
new EmulsionDbContext(":memory:")
7 changes: 7 additions & 0 deletions Emulsion.Database/Initializer.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module Emulsion.Database.Initializer

open Microsoft.EntityFrameworkCore

let initializeDatabase(context: EmulsionDbContext): Async<unit> = async {
do! Async.AwaitTask(context.Database.MigrateAsync())
}
58 changes: 58 additions & 0 deletions Emulsion.Database/Migrations/20210926114410_Initialize.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// <auto-generated />
namespace Emulsion.Database.Migrations

open System
open Emulsion.Database
open Microsoft.EntityFrameworkCore
open Microsoft.EntityFrameworkCore.Infrastructure
open Microsoft.EntityFrameworkCore.Metadata
open Microsoft.EntityFrameworkCore.Migrations
open Microsoft.EntityFrameworkCore.Storage.ValueConversion

[<DbContext(typeof<EmulsionDbContext>)>]
[<Migration("20210926114410_Initialize")>]
type Initialize() =
inherit Migration()

override this.Up(migrationBuilder:MigrationBuilder) =
migrationBuilder.CreateTable(
name = "TelegramContents"
,columns = (fun table ->
{|
Id =
table.Column<Guid>(
nullable = false
,``type`` = "TEXT"
)
|})
,constraints =
(fun table ->
table.PrimaryKey("PK_TelegramContents", (fun x -> (x.Id) :> obj)) |> ignore
)
) |> ignore


override this.Down(migrationBuilder:MigrationBuilder) =
migrationBuilder.DropTable(
name = "TelegramContents"
) |> ignore


override this.BuildTargetModel(modelBuilder: ModelBuilder) =
modelBuilder
.HasAnnotation("ProductVersion", "5.0.10")
|> ignore

modelBuilder.Entity("Emulsion.Database.Models.TelegramContent", (fun b ->

b.Property<Guid>("Id")
.IsRequired(true)
.ValueGeneratedOnAdd()
.HasColumnType("TEXT") |> ignore

b.HasKey("Id") |> ignore

b.ToTable("TelegramContents") |> ignore

)) |> ignore

33 changes: 33 additions & 0 deletions Emulsion.Database/Migrations/EmulsionDbContextModelSnapshot.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// <auto-generated />
namespace Emulsion.Database.Migrations

open System
open Emulsion.Database
open Microsoft.EntityFrameworkCore
open Microsoft.EntityFrameworkCore.Infrastructure
open Microsoft.EntityFrameworkCore.Metadata
open Microsoft.EntityFrameworkCore.Migrations
open Microsoft.EntityFrameworkCore.Storage.ValueConversion

[<DbContext(typeof<EmulsionDbContext>)>]
type EmulsionDbContextModelSnapshot() =
inherit ModelSnapshot()

override this.BuildModel(modelBuilder: ModelBuilder) =
modelBuilder
.HasAnnotation("ProductVersion", "5.0.10")
|> ignore

modelBuilder.Entity("Emulsion.Database.Models.TelegramContent", (fun b ->

b.Property<Guid>("Id")
.IsRequired(true)
.ValueGeneratedOnAdd()
.HasColumnType("TEXT") |> ignore

b.HasKey("Id") |> ignore

b.ToTable("TelegramContents") |> ignore

)) |> ignore

9 changes: 9 additions & 0 deletions Emulsion.Database/Models.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Emulsion.Database.Models

open System
open System.ComponentModel.DataAnnotations

[<CLIMutable>]
type TelegramContent = {
[<Key>] Id: Guid
}
14 changes: 14 additions & 0 deletions Emulsion.Tests/Database/InitializerTests.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module Emulsion.Tests.Database.InitializerTests

open System.IO
open Emulsion.Database
open Xunit

[<Fact>]
let ``Database initialization``(): unit =
async {
let databasePath = Path.Combine(Path.GetTempPath(), "emulsion-test.db")
use context = new EmulsionDbContext(databasePath)
let! _ = Async.AwaitTask(context.Database.EnsureDeletedAsync())
do! Initializer.initializeDatabase context
} |> Async.RunSynchronously
2 changes: 2 additions & 0 deletions Emulsion.Tests/Emulsion.Tests.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<Compile Include="Xmpp\SharpXmppHelperTests.fs" />
<Compile Include="Xmpp\SharpXmppPingHandlerTests.fs" />
<Compile Include="Xmpp\EmulsionXmppTests.fs" />
<Compile Include="Database\InitializerTests.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Akka.TestKit" Version="1.3.12" />
Expand All @@ -37,5 +38,6 @@
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
<ProjectReference Include="../Emulsion/Emulsion.fsproj" />
<ProjectReference Include="..\Emulsion.Database\Emulsion.Database.fsproj" />
</ItemGroup>
</Project>
24 changes: 24 additions & 0 deletions Emulsion.sln
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ ProjectSection(SolutionItems) = preProject
.github\workflows\docker.yml = .github\workflows\docker.yml
EndProjectSection
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Emulsion.Database", "Emulsion.Database\Emulsion.Database.fsproj", "{0111F688-1AE2-4B5D-BF46-D60B64078788}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".config", ".config", "{D03C4F4A-9806-46AA-8654-14363DFB3FBE}"
ProjectSection(SolutionItems) = preProject
.config\dotnet-tools.json = .config\dotnet-tools.json
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{12336258-82C7-4C09-A73F-8D0B146578B2}"
ProjectSection(SolutionItems) = preProject
docs\create-migration.md = docs\create-migration.md
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -63,6 +75,18 @@ Global
{1B3B65DD-FD58-45FA-B6FF-8532B513A7D9}.Release|x64.Build.0 = Release|x64
{1B3B65DD-FD58-45FA-B6FF-8532B513A7D9}.Release|x86.ActiveCfg = Release|x86
{1B3B65DD-FD58-45FA-B6FF-8532B513A7D9}.Release|x86.Build.0 = Release|x86
{0111F688-1AE2-4B5D-BF46-D60B64078788}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0111F688-1AE2-4B5D-BF46-D60B64078788}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0111F688-1AE2-4B5D-BF46-D60B64078788}.Debug|x64.ActiveCfg = Debug|Any CPU
{0111F688-1AE2-4B5D-BF46-D60B64078788}.Debug|x64.Build.0 = Debug|Any CPU
{0111F688-1AE2-4B5D-BF46-D60B64078788}.Debug|x86.ActiveCfg = Debug|Any CPU
{0111F688-1AE2-4B5D-BF46-D60B64078788}.Debug|x86.Build.0 = Debug|Any CPU
{0111F688-1AE2-4B5D-BF46-D60B64078788}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0111F688-1AE2-4B5D-BF46-D60B64078788}.Release|Any CPU.Build.0 = Release|Any CPU
{0111F688-1AE2-4B5D-BF46-D60B64078788}.Release|x64.ActiveCfg = Release|Any CPU
{0111F688-1AE2-4B5D-BF46-D60B64078788}.Release|x64.Build.0 = Release|Any CPU
{0111F688-1AE2-4B5D-BF46-D60B64078788}.Release|x86.ActiveCfg = Release|Any CPU
{0111F688-1AE2-4B5D-BF46-D60B64078788}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{7D1ADF47-BF1C-4007-BB9B-08C283044467} = {973131E1-E645-4A50-A0D2-1886A1A8F0C6}
Expand Down
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,22 @@ where `$EMULSION_VERSION` is the version of the image to publish.
Documentation
-------------

- [Changelog][changelog]
- [License (MIT)][license]
Common documentation:

- [Changelog][docs.changelog]
- [License (MIT)][docs.license]

Developer documentation:

- [How to Create a Database Migration][docs.create-migration]

[andivionian-status-classifier]: https://github.com/ForNeVeR/andivionian-status-classifier#status-aquana-
[changelog]: ./CHANGELOG.md
[docker-hub]: https://hub.docker.com/r/codingteam/emulsion
[docs.changelog]: ./CHANGELOG.md
[docs.create-migration]: ./docs/create-migration.md
[docs.license]: ./LICENSE.md
[dotnet-runtime]: https://www.microsoft.com/net/download/core#/runtime
[dotnet-sdk]: https://www.microsoft.com/net/download/core
[license]: ./LICENSE.md
[telegram]: https://telegram.org/
[xmpp]: https://xmpp.org/

Expand Down
15 changes: 15 additions & 0 deletions docs/create-migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
How to Create a Database Migration
==================================

This article explains how to create a database migration using [EFCore.FSharp][efcore.fsharp].

1. Change the entity type (see `Emulsion.Database/Models.fs`), update the `EmulsionDbContext` if required.
2. Run the following shell commands:

```console
$ dotnet tool restore
$ cd Emulsion.Database
$ dotnet ef migrations add <migration-name>
```

[efcore.fsharp]: https://github.com/efcore/EFCore.FSharp

0 comments on commit 2ca51af

Please sign in to comment.