Entity Framework Core on Mac

I recently decided to get up to speed on the latest ASP.NET, C#, and Entity Framework Core offerings. Plus, I know firsthand that getting certain ASP.NET Core things working on a Mac isn’t always as easy as it’s made out to be. So I thought I’d document as I go.

Entity Framework Core on Mac
Entity Framework Core on Mac

I recently decided to get up to speed on the latest ASP.NET, C#, and Entity Framework Core offerings and see what’s changed since the last time I used them. My interest peaked with the latest .NET 7 release.

Plus, I know firsthand that getting certain ASP.NET Core things working on a Mac isn’t always as easy as it’s made out to be. So I thought I’d document as I go and then include it all here in case it helps others learn a little more about Entity Framework Core and getting things working on a Mac.

The Goal

By the end of this write-up I want to:

  1. Create a working ASP.NET Core MVC application using Entity Framework accessing Azure SQL. Just a default MVC app - enough to get EF tested and working
  2. Create an Azure SQL database for the application to access
  3. Take a code-first approach - create the classes I envision to represent my data structure and then use Entity Framework to generate that schema on the database side
  4. Have the project checked into a GitHub repository so that I can pull it all down to a Windows desktop and work on it from there as well if I choose to

This article assumes you are at least familiar with ASP.NET, MVC, Entity Framework, and getting around in a terminal window. I’m not trying to teach those things, just show you how to get it all working on a Mac.

Homebrew package manager
Homebrew package manager

HomeBrew Package Manager and Necessary Packages

I highly recommend installing and using HomeBrew as your package manager on the Mac. HomeBrew makes it super easy to install, update, and uninstall the various software and tools you need on the Mac as you are writing code.

You can use HomeBrew to manage:

  • Languages - I use it to manage my lua, node, and python installations
  • Tools - I use it to manage tools like git, putty, wget, gulp, and powershell
  • Apps - I used it to manage command-line installs for browsers, image software, etc
  • Databases - I use it to manage mongodb and sqlite

Anyway, go grab it if you don’t already have it:

The Missing Package Manager for macOS (or Linux).

Then, you will want to install the following:

  1. git
  2. dotnet-sdk
  3. git-credential-manager-core
Git and GitHub


Git will be the version control you will use in the project, and you will connect to a GitHub repository to store your source code.

Run “brew install git” from a terminal window.

Once installed, run “git -v” to verify you get a version response and know it’s installed.

.NET command-line interface


Important: This is an important package needed for the “dotnet” CLI functionality. Be sure you install the “dotnet-sdk” package and not the “dotnet” package. You can do a “brew search /dotnet/” to see a list of all available brew packages and you’ll see that there are multiple choices. Choose the right one!

Run “brew install dotnet-sdk” from a terminal window.

Once installed, run “dotnet –info” to verify you get a .NET SDK installed version response and know it’s installed.

Git Credential Manager
Git Credential Manager


Important: This is an area where I lost a lot of time on the Mac. I’ve used my Mac across multiple organizations and projects and had a lot of different things hanging around on it. See below.

Somewhere along the way, I did some customization to how I authenticate to GitHub when doing git commands. The result is that in this project when I fleshed out the initial code base and wanted to get it pushed up to a GitHub repository, I was getting the following error trying to Publish to the repo from within VS Code:

ERROR: Repository not found.

Now, for some folks, this can be a situation where you’ve been added to a project but not given the proper permissions for the repository you’re trying to access. That’s a simple enough issue to troubleshoot and resolve.

In my case, this was against a repository that I created and own and can connect successfully to from within VS Code just not actually push to.

The issue ended up being related to bad credentials during the TLS handshake, due to my GitHub authentication customization weirdness.

The fix is to install the git credential manager.

Run “brew install git-credential-manager-core” from a terminal window.

WHAT IT DOES: Once installed, the first time you do a TLS push-type activity, the credential manager will actually prompt you for your credentials. It will store them securely, then work behind the scenes from that point forward to proxy your credentials via TLS when necessary and allow the secure connection to work without intervention.

Once I did this, my git commands worked fine.

Here are some more specific instructions if you end up needing them:

git-credential-manager/install.md at release · GitCredentialManager/git-credential-manager
Secure, cross-platform Git credential storage with authentication to GitHub, Azure Repos, and other popular Git hosting services. - git-credential-manager/install.md at release · GitCredentialManag...


Create a Working ASP.NET MVC Core Application

Working on the Mac in VS Code means not having all the same tooling we would have on a Windows desktop using Visual Studio Community or another fuller edition. Don’t get me wrong it’s totally doable and still a great experience as we’ll see. However, some things aren’t quite as easy as we would have otherwise. But I wanted to walk through getting this all working on VS Code because a lot of developers are trying this and having some issues.

I actually like this because it helps you understand what’s going on under the hood. And it helps you actually appreciate what .NET Core can do as a fully cross-platform solution.

Visual Studio Code
Visual Studio Code

Visual Studio Code

On the Mac, we will use Visual Studio Code. VS Code is a great IDE that brings a lot of awesome tooling over from the fuller Visual Studio editions. It also has a huge number of extensions that bring out even more functionality for us.

I’ll leave it to you to get VS Code installed. I haven’t seen any problems actually getting it installed so I don’t have any issues to cover for you.

VS Code Extensions

Here are the extensions that I’ve found the most helpful when working with ASP.NET and Azure database code in VS Code. I have lots of extensions installed for lots of different languages and other projects. So rather than doing a screenshot, I’ll list them here for you and you can look them up and install them.

Just run VS Code and click the Extensions icon on the left-hand navigation, then search for each of the following by name and install them:

  1. Azure Account
  2. C#
  3. Intellicode
  4. NuGet Package Manager
  5. Prettier - Coe Formatter
  6. SQL Server
  7. Material Icon Theme (just an icon theme but I sure like it)

Make sure you have an Azure portal account already. A free trial account or a full account will do.

DotNet CLI Support

One of the cool things about .NET Core is that it’s cross-platform. It runs on Windows, Mac, Linux, and even other operating systems too. To support this, Microsoft offers command-line tools to build the various things we need for .NET Core on multiple platforms.

Since we are on a Mac, we will use the DotNet command line (CLI) for a few different things. We will use it for things like:

  • Creating a default .NET MVC app
  • Creating EF (entity framework) data migration and database update packages

It sounds harder than it really is. You just have to make sure you have the right stuff installed, and you have to document the command-line commands to run when you need them.

Creating a Default ASP.NET MVC Application

Now that all the installation pieces are in place, we can finally get to some code!

We’ll use the DotNet CLI to generate a default MVC app for us. Let’s assume we want to create our default MVC app in a folder under our current folder called mvctestapp. Do the following:

  1. mkdir mvctestapp && cd mvctestapp
  2. dotnet new mvc

That’s it! You should see something like the following:

Default ASP.NET MVC app
List of generated files from dotnet new mvc command

Note: you will create the DataContext and DataModels folder a bit later.

You have a full ASP.NET MVC project with all the source code for configuration, controllers, models, and views. You can run the app right now if you want:

  1. From the command line, type “code .” to run VS Code and pull up the current code folder
  2. Choose Terminal->New Terminal from the top menu to open a terminal window if one is not open already
  3. Type dotnet run
  4. dotnet will use the launchsettings.json to start a web server at a particular port
  5. Click the link provided in the terminal window to see your MVC app at that particular port

If for some reason you didn’t see that, you can run the following command to see a list of all the templates currently available for the dotnet new command to install:

dotnet new list

The list is actually quite long. Here’s the beginning of my resulting list:

dotnet new list command output example
dotnet new list output of available templates

If you aren’t seeing that, go back and double-check that you properly installed the dotnet-sdk package using Brew.

Issues Running MVC App Multiple Times On Mac

An issue I came across, which I don’t think has been permanently solved yet, is that your app can sometimes continue to run even when you stop it. When you run your app a second or subsequent time, the prior web server is sometimes still running on that same port. You receive an error that it won’t launch on subsequent runs because something is already running on that port.

The default configuration for your MVC app chooses say port 5000 (see your launchsettings.json) to run on when you debug or run your app locally. You can see this when you run it and look at the address bar.

If you run across this, here are some terminal commands you can use to see if something is running on a port and if so kill that process.

lsof -i :5000

That will “list open files and the processes that use them” at port 5000. Change the port to whatever port you are using. If you run it and it shows one or more lines, that means you likely still have a web server process running that is accessing files on that port. It will give you the PID (process id) for any processes running.

You can then run the following command to kill the process with that PID (32408 for example):

sudo kill -9 32408

You can also do it in one line like this:

sudo kill -9 $(lsof -t -i :5000)

Add Entity Framework Support

Ok now that we have a working and runnable default ASP.NET MVC Core application, let’s add the Entity Framework Core support that we need in order to make it an EF Core application too.

To do this, we will use the dotnet CLI again. We’ll use it to add the appropriate Entity Framework Core packages we need for the project.

NOTE: I have to admit, I have not been able to find a good way to actually search for and find the nuget packages related to EntityFrameworkCore. I assume there is now a way to search and locate these but I haven’t been able to find it and it didn’t previously exist. So here I’ll include the packages because I happen to know them. But surely there’s a way to get this list somewhere?!

Go to a terminal window, in your application folder, and run the following to install each of these packages into the project:

dotnet add package Microsoft.EntityFrameworkCore

dotnet add package Microsoft.EntityFrameworkCore.Design

dotnet add package Microsoft.EntityFrameworkCore.Tools

dotnet add package Microsoft.EntityFrameworkCore.Tools.DotNet

dotnet add package Microsoft.EntityFrameworkCore.SqlServer

Note: developers often test locally with SQLite - to add that you can run:

dotnet add package Microsoft.EntityFrameworkCore.Sqlite

These are the packages necessary to work with Entity Framework Core at design time and run time, and to work with SqlServer as a database.

After you do this, you’ll see changes to things like your .csproj file to now include the necessary additions.

Now we can actually start adding some Entity Framework database code! But before we do, let’s go set up an Azure SQL database so we know we have something to connect to.

Create an Azure SQL Database

There’s not a lot we need to cover here. I assume you have a trial or a full Azure account already. If not you can get one very easily.

Creating Azure SQL In The Portal

With a trial account, I think you can get a free Azure SQL database for 12 months. I think it’s a 250 GB S0 instance with 10 database transaction units (processor usage). Check out more and all the free services here:

Free Services | Microsoft Azure
Explore free Azure services, including popular services free for 12 months and 55+ other services free always. See which types of these services are free up to a monthly amount.

Even if you don’t have a free account still, you can set up an Azure SQL Database and only pay around $5/mo for it.

NOTE: when you go into the Azure portal and start to configure your Azure SQL database, it will start to show your monthly cost estimate in the hundreds of dollars. Just be sure to choose the Development option instead of the Production option and that will drop the price (and performance) to more like $5 per month using a default configuration.

Also, I chose to enable both Azure Active Directory and SQL Login options for connecting to the database. I really did this because I’m more used to connecting via sql login so wanted that option. But I need to explore better connection options so I enabled both.

I’m used to the IAM approach on AWS so I want to explore stronger AAD integration for Azure SQL to see what it has to offer. For now, this exercise will use a sql login though.

Verifying Database Connectivity From VS Code

Once you have an Azure SQL database created in the portal, let’s verify we can connect to it from VS Code. This is also where we’ll get to use some of the nice extensions we installed.

We will use the SQL Server extension to create a profile and connect to the Azure SQL database we just created. We are using this because it's integrated directly into VS Code and we didn't want to assume you already had SQL server management studio installed. That is definitely another option for you though.

  1. If not already, change to your project folder from a terminal window
  2. Type “code .” to run VS Code for the current folder project
  3. Click the “SQL Server” icon in the left-hand navigation. If you don’t see it, open up your extensions and make sure you installed and enabled the SQL Server extension as mentioned in the previous section
  4. Click the option to add a new connection
  5. When prompted for the server name, provide that as it is displayed on your portal Azure SQL database overview screen. An example is yourdatabase.database.windows.net
  6. When prompted for the database name (optional), just press enter
  7. When asked for authentication type, choose which you want. I went with SQL Login for now but I will be researching this more
  8. Enter the sql login username and password you created during your database setup
  9. Choose Yes or No to save. I chose Yes just so I don’t get prompted every time
  10. Enter a name to save your profile settings so that you can just choose this for next time

Just In Case Azure Connection Is Not Established Yet From VS Code

Note: I have occasionally gotten errors when connecting to my Azure SQL database using the SQL Server extension. Sometimes I see a timeout error, and sometimes the error is more generic. The few times it has happened, I simply double-check my entries and try again and I get in. So be aware this may happen to you.

You Are Connected To Your Azure SQL Database

Once you get connected via the extension, it will display the following for you and you know you are in:

SQL Server VS Code Extension sample output
SQL Server extension display

You are connected!

Now… finally… let’s get Entity Framework connected to our database and take a simple code-first approach to create some tables in our database.

Code-first approach
Code-first approach

Take a Code-First Approach

You should still have VS Code pulled up with your project. Close out any of the SQL Server extension windows that were opened when you tested that. It's time to start taking a code first in entity framework core approach.

Now we will:

  1. Create a class representing a table and attributes to add to our database
  2. Create a database context so EF can talk to our Azure SQL database
  3. Create an EF migration package
  4. Run that migration package
  5. View our newly created table in our Azure SQL database

Code-First Approach To Creating an Entity Framework Table

We want to create a folder to store our EF data objects. These objects will be .NET classes with some decorators to help EF understand what we want to do in a few special situations. This is the code-first approach. Create classes that represent the objects we’ll be working with in our application, then use EF to generate the data models and actual data schema we need based on those classes.

Typically we’d create a Models folder for this. But since we’re creating EF functionality directly in our template MVC app, a Models folder has already been created. To avoid confusion, we’ll create separate folders for our EF needs.

You could also make a case for using the existing Models folder. I prefer to keep the MVC models and the EF models separate - at least for now.

For this exercise let’s pretend we’re creating an MVC app that will be used to manage tweets. We will eventually want to bulk upload tweets to this system along with scheduled dates on which to send them out. The application will support the bulk upload and verification of the tweets, bulk selecting tweets for approval to be scheduled and sent, and display and edits of tweets in the system.

So let’s start with a simple Tweet class object.

Create a DataModels folder.

In that folder, create a new class file called JustaTweet.cs and open that class file.

Create a simple public class with some attributes in it that make sense for a potential tweet system like this. Here’s an example you might use:

JustaTweet.cs class
JustaTweet class

Add the namespace at the top:

Using mvctestapp.DataModels;

Add the [Key] decorator above the TweetId attribute as follows:


public int TweetId { get; set; }

The [Key] decorator tells EF that we want to use this field as the primary key for this table. When it finds a field named Id it will automatically use that as the primary key but we can use this decorator when Id does not exist or we need to override as necessary.

You will notice the red squiggly under [Key]. We haven’t added the appropriate using statement(s) to support this. However, we have added the packages we need and VS Code knows how to fix this for us. So choose the Quick fix option when your mouse is over the red squiggly to fix it.

Choose the first recommended using statement from the list and there you go - problem resolved as VS Code adds the using statement we need to our code.

You just created a class that EF will use to generate a table and columns in our database representing this object. Now let’s tell EF how to connect to our Azure SQL database.

Create our EF Data Context to Azure SQL Server

Create a DataContext folder.

In that folder, create a new data context class file called JustaContext.cs and open that class file.

This is where we will create a database context for each of the database tables we’ll be working with. So far that’s just our JustaTweet table.

We’ll create a new data context class and derive it from the EF DbContext class. To be honest I don’t remember where I grabbed this starter template from but I’ll include it here anyway and we’ll build on it.

JustaContext.cs class file
JustaContext class

Notice that in the overridden OnConfiguring method we are telling EF to use SQL Server as our database. This is basically where we can plug in any number of database providers that EF supports. When using SQLite, you would do that here. Once you eventually configure a debug build using SQLite and a production build using Azure SQL, you will likely have additional code in the Program.cs file to use each appropriately depending on the build.

Add the namespace:

namespace mvctestapp.DataContext;

Let’s work through our red squigglies and get our missing using statements added.

For our DbContext red squiggly, use the quick fix option to add our EF core framework using:

using Microsoft.EntityFrameworkCore;

For our JustaTweet reference, we need to add a using to our DataModel:

using mvctestapp.DataModels;

If all went well, that should be all you need!

Sometimes you’ll see a specific using statement for the database provider you are using, like this:

using Microsoft.EntityFrameworkCore.SqlServer;

But technically that shouldn’t be necessary since that’s included when in the EntityFrameworkCore using statement. It will be grayed out if unnecessary.

Now all that’s left is to set our connection string on the UseSqlServer method call. Jump over to our Azure portal overview page for your database, and grab the appropriate connection string to plug in. In my case, I used a sql login connection string.

Be sure to change the password.

Note: I do not recommend hard-coding connection strings like this! A better approach is to use application variables or even Azure Key Vault. But, as in most samples, we’ll keep this simple.

Now we should be ready to create a migration package and have EF make these changes to our Azure SQL database for us.

Create a Migration Package

An EF migration package provides a way to incrementally update a database schema to keep it in sync with changes being made to EF code, while also preserving existing data in the database.

This is what makes the code-first approach so handy. We can be incremental about our code design and prototyping, use EF to manage our database interaction, and also have EF keep our database schema and data in sync with all these incremental changes we are making in our code.

I’m not going to pretend I know how well this works on larger projects with complex database schemas, millions of rows of data, and certain column types that historically make incremental data changes challenging. But from the perspective of a code-first approach early in a project, this is pretty neat.

Creating an entity framework migration package on the Mac

When using Visual Studio Community or other full editions on a Windows machine, VS supports shelling out to a Package Manager Console. Package Manager Console is a powershell app that makes it easy to run the commands necessary for creating migration packages and then running them to update a database.

When doing this work on a Mac, we need to step back to the dotnet CLI to do this work. But hey that’s ok! If we installed everything correctly, it’s just a matter of knowing what commands to use to create our package.

We know it's going to be a dotnet ef command, so do something like this to learn a little more about what the command might be:

  1. Go to a terminal window in your VS Code, or separately but in the correct folder
  2. Run “dotnet ef –help” - to see what it shows you - see the migrations option?
  3. Run “dotnet ef migrations –help” - see the add option?

After this research, you can surmise that we can run this to create our first EF migration package for this project:

dotnet EF migrations add InitialCreate

It’s kind of deceiving how little it shows and how much it actually did. But the interesting stuff is in your project. Take a look at the new Migrations folder and files that were created. I won’t go into all the detail here but this is the snapshot information that EF can now use to sync the database schema with what exists here in the code.

So now let’s take that code first approach. Let’s run the code that creates the corresponding database schema objects for us.

Run The Migration Package To Update Our Database

We know we have another dotnet ef command to update our database, so we’ll follow a similar approach. Here’s your hint:

dotnet ef database –help

dotnet ef database --help output
dotnet ef database --help output

Follow the dotted line and you’ll see that we should be able to run the following to update our database with any migration packages that haven’t been applied yet:

dotnet ef database update

There are numerous other options but we’ll keep it simple here. Plus, this is really all we need.

So run it! Build started… Build succeeded… Applying migration… Done.

View Our Table!

Pull up your SQL Server extension, refresh your table folder, and you will now see your JustaTweet database table and its columns!

JustaTweets table columns displayed in SQL Server extension
SQL Server extension output

Just for grins, try adding another column and follow the same process:

  1. Edit your JustaTweet.cs class and add another column
  2. Run “dotnet ef migrations add AddedColumnX
  3. Run “dotnet ef database update
  4. View your modified database table!

There is definitely some value to this code-first approach when doing incremental prototyping or small projects - at least I can see potential there. I’m still not sure how well this works for larger projects with lots of existing data and more complex schemas. But I’ll add this to my list of research I need to do in order to have a more data-based opinion.

Create a GitHub Repository And Publish

We’ve done quite a bit so far code-wise. We’ve:

  1. Created a fully working simple ASP.NET MVC Core app
  2. Added Entity Framework Core support to it
  3. Added some custom classes for our objects, and decorated them with EF decorators
  4. Used the dotnet CLI to create migration packages and corresponding source changes

Let’s get all this saved into version control so that we have it there and available and versioned.

For this exercise, we’ll use GitHub. I’ll assume you have a free GitHub account. If not, go create one now.

Once that’s done, you shouldn’t have any connection problems since we already went through the fun of verifying you have the git credentials manager running. If this is the first time you are doing all this, then as you follow the instructions below, at some point you’ll be prompted to log in to GitHub. Follow the dotted line to do that, and your credentials will be securely stored and managed for you from that point forward.

  1. Click the Source Control option on the VS Code left-hand side
  2. Click Publish to GitHub
  3. The extension will want to sign in to GitHub - allow it
  4. Choose the Publish to GitHub private repository option (public if you want)

You probably haven’t created some good default files yet like README.md and .gitignore. When it asks what files to include, EXCLUDE the following since these don’t need to be in version control:

  1. obj
  2. bin
  3. A new repository by that name will be created for you and the code uploaded. You’ll see a message in the lower right corner verifying things and with a link to view that new repo in GitHub:
GitHub repository display
GitHub repository

What’s Next

That was quite a bit of work but hey look at what you accomplished!

  • You got an ASP.NET MVC Entity Framework Core application working on your mac
  • You learned a bit about Homebrew as a package manager for the mac
  • You learned a bit about the dotnet CLI
  • You connected to Azure SQL and pushed code-first changes
  • You got all the code stored up in GitHub version control

And hopefully, you also learned a few things about the challenges that sometimes come along with doing all this on the mac.

I hope I showed you some things that will save you time later and maybe make you want to learn more about Entity Framework Core development on a mac.

Maybe in future articles, we can dig in more and:

  1. Replace our BAD hard-coded database connection string with a better approach
  2. Add some unit tests
  3. Use CircleCI to demonstrate a continuous integration pipeline
  4. Add some basic grid display and data operations

On that last point, there is an excellent MvcMovie sample EF Core app to look at that includes grid and full CRUD operations. I think it's out on Microsoft Learn.

Until next time 🙂

Have you checked out my career boosting course?
Click Here to read about it and how to watch a free video preview.