Efcore: F# Support

Created on 24 Aug 2016  路  13Comments  路  Source: dotnet/efcore

Steps to reproduce

  • dotnet new -l F#
  • Add this code to program.fs
module Test
open System
open Microsoft.EntityFrameworkCore;
open Microsoft.EntityFrameworkCore.Metadata;
open Microsoft.EntityFrameworkCore.Metadata.Internal;
open Microsoft.Extensions.Options;

[<CLIMutable>] type Test = { Id: int; Name: string; }

let connectionString = "User ID=postgres;Password=test;Host=localhost;Port=5432;Database=TestDb;"

type TestDb() = 
    inherit DbContext()
    member val LadderChanges = Unchecked.defaultof<DbSet<Test>> with get, set
    override this.OnConfiguring(builder) = builder.UseNpgsql(connectionString) |> ignore

  • Add this to project.json
{
  "version": "1.0.0-*",
  "buildOptions": {
    "emitEntryPoint": true,
    "compilerName": "fsc",
    "compile": {
      "includeFiles": [
        "Program.fs"
      ]
    }
  },
  "tools": {
    "dotnet-compile-fsc": "1.0.0-preview2-*",
    "Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"
  },
  "frameworks": {
    "netcoreapp1.0": {
      "dependencies": {
        "Microsoft.FSharp.Core.netcore": "1.0.0-alpha-160629",
        "Npgsql.EntityFrameworkCore.PostgreSQL": "1.0.0",
        "Microsoft.EntityFrameworkCore.Relational": "1.0.0",
        "Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final",
        "Microsoft.NETCore.App": {
          "type": "platform",
          "version": "1.0.0"
        }
      }
    }
  }
}
  • dotnet ef migrations add f#1
  • dotnet ef database update

    The issue

Creating a migration in an F# project produces .cs migration files.

Project effsharptest (.NETCoreApp,Version=v1.0) will be compiled because Input items added from last build                                                                                            
Compiling effsharptest for .NETCoreApp,Version=v1.0                                                                                                                                                   
C:\Program Files\dotnet\dotnet.exe compile-fsc @c:\Users\nickacosta\projects\effsharptest\obj\Debug\netcoreapp1.0\dotnet-compile.rsp returned Exit Code 1                                             
c:\Users\nickacosta\projects\effsharptest\error FS0226: The file extension of 'Migrations\20160824164200_f#3.cs' is not recognized. Source files must have extension .fs, .fsi, .fsx, .fsscript, .ml o
r .mli.                                                                                                                                                                                               
c:\Users\nickacosta\projects\effsharptest\error FS0226: The file extension of 'Migrations\20160824164200_f#3.Designer.cs' is not recognized. Source files must have extension .fs, .fsi, .fsx, .fsscri
pt, .ml or .mli.                                                                                                                                                                                      
c:\Users\nickacosta\projects\effsharptest\error FS0226: The file extension of 'Migrations\QueueDodgeDbModelSnapshot.cs' is not recognized. Source files must have extension .fs, .fsi, .fsx, .fsscript
, .ml or .mli.                                                                                                                                                                                        
Compilation failed.                                                                                                                                                                                   
    0 Warning(s)                                                                                                                                                                                      
    3 Error(s)                                                                                                                                                                                        
Time elapsed 00:00:02.4520082      

Used vscode.

closed-by-design help wanted type-enhancement

Most helpful comment

For anyone watching this issue, we're collaborating on this over in the bricelam/EFCore.FSharp repo.

All 13 comments

Potential Workaround:

  • Move code into "src" folder
  • Move migrations folder outside of "src" folder.
  • Add a c# project.json to the "migrations" folder.
  • Add reference to "src" in project.json in the "migrations" folder.
  • Add a global.json outside of the "src" and "migrations" folder.

Global.json:

{
    "projects": ["src","Migrations"]
}
  • Back in the f# library, use the following overload for the DbContext's "OnConfiguring" method.
override this.OnConfiguring(builder) = builder.UseNpgsql(connectionString, (fun b -> b.MigrationsAssembly("Migrations") |> ignore)) |> ignore
  • "dotnet ef database update" should work now.

Triage: we would consider a PR in this area but we would also prefer to work on the plumbing necessary to make it possible to build a separate package that does this.

Out of curiosity... Will this be a problem for VB also? Are we talking 3 packages?

@nickolasacosta Yes, it would be nice if the same pattern could be applied to extend support to additional languages.

Here's some code to get started for anyone looking to generate migrations in a different language.
```C#
// Put this in your app. EF discovers and calls it at design-time.
class MyDesignTimeServices : IDesignTimeServices
{
public void ConfigureDesignTimeServices(IServiceCollection services)
=> services.AddSingleton();
}

```c#
class FSharpMigrationsCodeGenerator : MigrationsCodeGenerator
{
    public override string FileExtension => ".fs";

    public override string GenerateMigration(
        string migrationNamespace,
        string migrationName,
        IReadOnlyList<MigrationOperation> upOperations,
        IReadOnlyList<MigrationOperation> downOperations)
    {
        return "// TODO";
    }

    public override string GenerateMetadata(
        string migrationNamespace,
        Type contextType,
        string migrationName,
        string migrationId,
        IModel targetModel)
    {
        return "// TODO";
    }

    public override string GenerateSnapshot(
        string modelSnapshotNamespace,
        Type contextType,
        string modelSnapshotName,
        IModel model)
    {
        return "// TODO";
    }
}

For reference, see the C# implementation in CSharpMigrationsGenerator.cs.

I was looking to discuss adding F# Migration support for EF Core, and is something I'm interested in contributing to. Is this a good place to have this discussion?

Is F# database migrations something that fits in to the current timeline? Or is this in active development?

I was going to ask additional questions about architecture, but it seems that a proposed method has already been laid out. However, if parts of this need to be moved out to it's own project, then I assume that's a bigger discussion.

I'd love to start working on this if it is wanted, I've read through the contributing guidelines and want to make sure I would be making a desired contribution before I dove too deeply into this process.

I started work on the plumbing in bricelam:lang.

10154 will make it easier to use in a separate package.

As far as the F# implementation is concerned, the above starting point is still correct.

Sounds great, I'm am actively working on this then, as for patterns I'm following the C# code as I get into the guts of it.

I'm also interested in contributing to this
@tylerhartwig, are you still working on this? I have made started making some progress myself following the C# code patterns and translating the output to F#
What I've done so far (very much work in progress) is at simontaite:6401-fsharp

Marking for re-triage. The plumbing necessary to make this possible is out for review: #10289

10154 will make consuming a separate package as trivial as installing it into the startup project.

We should discuss whether we want to maintain an F# (and VB.NET) package or whether it should be published by a third party.

Triage decision: we will continue to help make it possible and easy for third-parties to create packages providing support for languages other than C#, but we won't own or maintain those packages as part of the EF code. This is because we believe the community is better able to understand best practices and special requirements of other languages on which the EF team are not experts.

Is there an effort somewhere to supply a package that generates migrations as F# code? My understanding is that this should now be possible but from the discussions above it is unclear if any of the attempts led to a usable baseline for F# code generation. We could use this in a project and could help progressing this.

For anyone watching this issue, we're collaborating on this over in the bricelam/EFCore.FSharp repo.

Was this page helpful?
0 / 5 - 0 ratings