Creating A F# Data Layer Using Entity Framework Core

I’ve been working on a stackoverflow clone that’s current written in C#. I wanted to try using F# at some point, so decided to convert my data layer from C# to F#. It took me awhile to piece together the necessary information in order to do that. (This article definitely help me!) I thought it was worth documenting the process for anyone else needing to do the same.
This article will describe in detail how to interact with an F# data layer from C# code. Because C# is directly interacting with F#, I’m going to be doing some F# things for the sake of working with C#. I’ll point those out along the way. Also, the only data piece that’s not in F# is the migration list because EF Core doesn’t provide native support for that at the time of writing. More on that below.
I’m also brand new to F#. The purpose of this article is more detailing how to setup projects in order to run F# as your data layer. I’m not yet in the place to recommend best practices around using F# in your data layer. That will come in time.
Snippets of the app are provided below, but please check the github for complete work example.
Outside of that, lets dive in.
Project Setup
Let’s go ahead and setup the two projects that we’ll be using. One F# project for the data layer and a C# project for the API layer.
I’m using Dotnet 2.2 release and I’ve also tested using preview versions of 3.0 release. In Visual Studio, create a new project, and select the ASP.NET Core Web Application.

Select desired name, then select the API option on the next page. I also unselected the button “Configure for HTTPS” on the right.

After clicking “Create” you’ll should see your basic C# API project created.

Now let’s create an F# project. Add a new project, ensure on the top right that F# is selected at the language, click the Class Library type.

Provide whatever name you desire, then click create and you should see the following setup.

You have a C# API layer and a F# class library. Now let’s setup the dependencies.
Installing EF Core
Lets install our required EF Core nuget packages in the necessary projects. Open up your Package Manager Console, ensure that the API project is the default project and run the following commands.
> Install-Package Microsoft.EntityFrameworkCore.Tools -Version 2.2.6
Then change the default project to your Db project and run the following command.
> Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 2.2.6
That should be all you need for required dependencies. Lets start coding.
Data Layer
The first thing we need are some entities. I’m continuing with the stackoverflow clone, so I’m going to model a simple User and Question relationship.
I’m creating a new F# file that I’ve called Entity.fs. Then replace the generated file with the following.
This file ultimately ended up a lot longer than originally planned. Using the AllowNullLiteral tag forced me to use a class instead of a record type. If I was not interfacing with C#, I would have used a record type. Here is an example of record types just for reference, so much shorter.
If you use record types you need to add the CLIMutable attribute. Adding the CLIMutable attribute causes it to be compiled to a Common Language Infrastructure (CLI) representation with a default constructor with property getters and setters. Which I believe means it acts more like a class.
Also the order of types and files matter in F#. F# can only use items that are previously defined. Take the following example where I replace the “and” on line 16 with “type”.

The compiler now doesn’t know how to find the User type because it’s defined below the Question. I don’t know the technical explanation, but using an and to join the definition of these types allows them to reference each other.
If you run into this problem between files, you’ll need to move files around the project in order for it to compile.
You can right click on an F# file, and choose to Move Up or Move Down. If you get any errors saying a type is not defined when it clearly is in your project, make sure that the definition occurs before the usage.

With that explained, now lets create a context file to manage connections to our database. Add a new file to your F# project, call it FSharpDataContext. Replace with the following.
If you’re coming from C# all this looks familiar, just in a condensed version. If your User and Question type give you issues, make sure you right click and move the FSharpDataContext.fs below your Entity.fs as explained above.
Now lets create a sample Repository. Because I’m calling this data layer from C#, I’m going to create an interface and a class for my Repository. If I was implemented the entire web app in F# I would probably go a different route.
If you’ll notice in the interface, I provided the two different ways to declare the signature of the method. GetQuestions v. CreateQuestion. One using syntax familiar to C#, the other using F# syntax. They are equivalent and you can pick which one you would prefer.
I’ve also provided two implementations of a GetQuestion method for reference. One called GetQuestionQuery that uses a query block and is not async. The other GetQuestion does not use a query block and is async.
We’ve defined all of our F#. Now lets setup a simple API to call our data layer.
C# API
Lets create a quick API in C# to connect to and query our data layer. First lets setup our QuestionsController.
You’ll notice that calling the QuestionRepository is exactly the same syntax as calling any other C# class.
We’ll also need to configure our API in our Startup.cs file. Open up that file and replace the ConfigureServices method with the following.
On line 5 we’re setting up dependency injection. Line 7–8 configures EF Core.
Now that we have the API setup, lets create our migrations.
Adding Migrations
This would now be the time where I fire up Package Manager Console and create my first migration in the Db project. Unfortunately doing that gives the following error message:
The project language ‘F#’ isn’t supported by the built-in IMigrationsCodeGenerator service. You can try looking for an additional NuGet package which supports this language; moving your DbContext type to a C# class library referenced by this project; or manually implementing and registering the design-time service for programming language.
Which basically means that EF Core doesn’t support F# as a language to generate migrations. Which was disappointing for me.
Googling search for a solution led me to this github repo, specifically issue #2, which says they were able to support it. They make a reference that is was added to nuget but I was unable to find it. If anyone knows more about this project or how to get it working please leave a comment.
Barring an F# alternative, the best next alternative I came up with was to have a separate C# project that only stored the migrations.
Create a C# project, then use the Package Manage Console to install the following nuget packages.
> Install-Package Microsoft.EntityFrameworkCore.Tools -Version 2.2.6
> Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 2.2.6
Make sure you add a reference for the Migrations project in your API project, otherwise you’ll get an error telling you to do so. Now run the following command in the Package Manage Console, ensure the migration file is specified as the default project.
> Add-Migration Initial -Context FSharpData.Db.FSharpDataContext
Which outputs the following error.
Your target project ‘FSharpData.Migrations’ doesn’t match your migrations assembly ‘FSharpData.Db’. Either change your target project or change your migrations assembly.
Change your migrations assembly by using DbContextOptionsBuilder. E.g. options.UseSqlServer(connection, b => b.MigrationsAssembly(“FSharpData.Migrations”)).
This is an issue when trying to store the migrations in a separate project than the context. Luckily the error message is very helpful. We need to configure EF Core to use a different project for our migrations. Return to our Startup.cs project and modify the AddDbContext method to specify the migrations assembly.
Then re-run the Add-Migration command and you should see your initial Migration. Make sure that Migrations references the Db project, then run the Update-Database command to create your new database.
> Update-Database
We have our database, our data layer and our API. Lets start up our project and interact with the APIs. I’ve included a postman collection for the port that this launches on my local machine. I’ve also added the equivalent repository and controller for Users. Feel free to play around with it!
In Closing
I hope you enjoyed the article! If you have any comments about EF Core or F#, feel free to leave a comment. As mentioned before, I’m just getting used to F# so I’m probably doing something incorrectly. I’ll write more as I spend more time in F#.
I’m Morgan Kenyon. I’m a .NET developer working in the DFW area. I find C# a great language to use and it’s also backed by a great ecosystem. I’m looking to getting into F# in the near future as well. I love solving hard problems and want to continue talking about the tech I use. If you found this article helpful or thought provoking leave a comment and lets connect over LinkedIn!