Azure Functions CLI - such a pretty logo for such an awesome functionality

How to access Entity Framework Core’s DbContext in an Azure Function?

This post was most recently updated on October 29th, 2020.

Reading Time: 4 minutes.

This post describes how you can access your Entity Framework Core model classes and the database context in your Azure Functions. In my example I’m using EF Core 2.1, but the main principle should be the same for later versions as well. Please note, that I use Azure functions runtime v2 (but it should work the same in v3 !)

Another easy one, that I was unable to find much guidance on!

But first, let’s start with the basics. Why would you want to have this setup? Why would you want to utilize your database context class and Entity Framework Core models in an Azure function?

A few scenarios come to mind!

Why use DbContext in your Azure Functions?

My case was pretty clear cut: I already had an ASP.NET Core MVC web application, which was using Entity Framework Core and SQL server. I wanted to add a scheduled task that would do some cleanup and analysis steps on the database – something non-urgent, but rather scheduled and running for maybe a few minutes at a time.

Additionally, these functions shouldn’t affect the actual web app’s execution and performance. So, a pretty good match for Azure Functions!

How to configure your Azure Functions to use EF’s DbContext?

Through some googling and a bit of trials and errors I came up with the following approach:

Time needed: 10 minutes.

Configuring an Azure Function to use a database context?

  1. Install latest Azure Functions Core Tools

    Access the download here:
    https://docs.microsoft.com/en-us/azure/azure-functions/functions-run-local?tabs=windows%2Ccsharp%2Cbash#install-the-azure-functions-core-tools

  2. Add dependencies

    You’ll need to add these dependencies – and hence the NuGet packages “Microsoft.EntityFrameworkCore” and “Microsoft.EntityFrameworkCore.SqlServer“. See an example below:

    using Microsoft.EntityFrameworkCore;
    using Microsoft.EntityFrameworkCore.SqlServer;


    Intellisense won’t ever tell you that you need the package and the dependency to Microsoft.EntityFrameworkCore.SqlServer. In fact, the using directive will appear unused, and Intellisense will likely suggest you should remove it! But you will need it to connect to an SQL server with EF.

    Visual Studio will prompt you to remove the dependency to SqlServer as it's "unnecessary". Don't remove it, though - you actually need it for the EF's DbContext to work in your Azure Functions!

    Visual Studio will prompt you to remove the dependency to SqlServer as it’s “unnecessary”. Don’t remove it, though – you actually need it for the EF’s DbContext to work in your Azure Functions!

    If you do, though, running the function will fail.

    Note: If you’re using the latest version of the Azure Functions CLI (2.18.3 at the time of writing this), you won’t in fact need the dependency for Microsoft.EntityFrameworkCore.SqlServer.

  3. Modify your database context class

    You’ll need to add a suitable constructor to your dbcontext class – somewhat like below:

    using Microsoft.EntityFrameworkCore;

    namespace DataLayer
    {
    public class ApplicationDbContext : DbContext
    {
    // entities etc omitted

    public ApplicationDbContext(DbContextOptions options) : base(options) { }

    }
    }


    This constructor is used in the next step – don’t worry about the contents.

  4. Instantiate your database context in your code

    -You can do something like this in your function:

    var options = new DbContextOptionsBuilder<ApplicationDbContext>();
    options.UseSqlServer(defaultConnection);

    var h = new HttpContextAccessor() { HttpContext = req.HttpContext };
    var db = new ApplicationDbContext(options.Options, h);


    And now you can use your database context like you’d use it anywhere – you could even wrap it in using -statements.

A code sample – my setup

After a bit of back and forth, I came up with a fully functional setup, that lets my Azure Function to run on a trigger (web request – but this could also be a schedule!) and make changes to the db. Treat it as proof of concept, though.

See below for my example code (for Azure Functions v2):

using System;
using Microsoft.Azure.WebJobs;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.SqlServer;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs.Extensions.Http;

namespace Koskila.Contoso.AzureFunctions
{
    public static class ContosoFunction
    {
        [FunctionName("ContosoFunction")]
        public static async Task<iactionresult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            string defaultConnection = Environment.GetEnvironmentVariable("DefaultConnection");
            var options = new DbContextOptionsBuilder<ApplicationDbContext>();
            options.UseSqlServer(defaultConnection);

            var h = new HttpContextAccessor() { HttpContext = req.HttpContext };
            var db = new ApplicationDbContext(options.Options, h);

            foreach (var p in db.YourEntities)
            {
                // Do something cool here
            }

            return new OkResult();
        }
    }
}

This piece of code should successfully connect to a MS Sql Database, and perform whatever cool stuff it needs to do!

Considerations

The approach is thread-safe, as it’s using different instances of the database context in different modules of the application. That doesn’t mean you won’t run into issues though: You can, of course, still run into a deadlock and other concurrency issues if you’re not careful about what you’re developing, but that’s no different to any other application.

Remember to either wrap your database context in an using-statement or dispose of it otherwise (in this model, the lifecycle isn’t managed by the runtime).

mm
5 1 vote
Article Rating
Subscribe
Notify of
guest
2 Comments
most voted
newest oldest
Inline Feedbacks
View all comments