Using Entity Framework with Azure Functions
Tags: dotnet, azure, serverless, entityframework
Published: 2019-05-28 16:41:47

---
title: Using Entity Framework with Azure Functions
published: true
description: How can you use Entity Framework Core with Azure Functions written in .NET Core? Check it out in a step-by-step sample.
tags: dotnet, azure, serverless, entity framework
cover_image: https://i.imgur.com/9hQWJRh.jpg
---

<< Update: The instructions below are still good but I did update my sample to use .NET Core 3.1 here if interested: https://github.com/jeffhollan/functions-chsarp-entitycore-3 >>

One of the exciting developments from Build this year was support for [dependency injection](https://aka.ms/functions-di-docs) in Azure Functions.  This means you can register and use your own services as part of functions.  While you've been able to use Entity Framework Core in the past, the pairing with dependency injection makes it a much more natural fit.  Let's create a simple Azure Function that can interact with stateful data using Entity Framework Core.  I'm going to create a very simple API that can get and set blog data in an Azure SQL Database.

## Adding entity framework to a function project

First up, I created a brand new v2 (.NET Core 2) Azure Functions project.  I selected the HTTP Trigger template to start with.  In order to use dependency injection I need to verify two things:

1. The `Microsoft.NET.Sdk.Functions` is at least `1.0.28`
2. Install the `Microsoft.Azure.Functions.Extensions` package to provide the API to use dependency injection

```powershell
Update-Package Microsoft.NET.Sdk.Functions
Install-Package Microsoft.Azure.Functions.Extensions
```

While we're at it, let's install the Entity Framework libraries.  ⚠️  These versions are *very* particular with the version of .NET you will be running.  So choose your version of these libraries thoughtfully.  At the time of writing this Azure is running .NET Core 2.2.3 so that's what I'll use.

```powershell
Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 2.2.3
```

I also want to take advantage of the design-time migration, so I'll install the tools needed to drive that.

```powershell
Install-Package Microsoft.EntityFrameworkCore.Design -Version 2.2.3
Install-Package Microsoft.EntityFrameworkCore.Tools -Version 2.2.3
```

### Add the entity models

Next, I'll create a very simple `DbContext` for the data models I want to interact with.  Let's just stick with the simple Blog and Posts entities.

```csharp
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Text;

namespace functions_csharp_entityframeworkcore
{
    public class BloggingContext : DbContext
    {
        public BloggingContext(DbContextOptions<BloggingContext> options)
            : base(options)
        { }

        public DbSet<Blog> Blogs { get; set; }
        public DbSet<Post> Posts { get; set; }
    }

    public class Blog
    {
        public int BlogId { get; set; }
        public string Url { get; set; }

        public ICollection<Post> Posts { get; set; }
    }

    public class Post
    {
        public int PostId { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }

        public int BlogId { get; set; }
        public Blog Blog { get; set; }
    }
}
```


### Write the function code to inject the entity context

I need to verify that I'm using constructors in my function classes so I can inject in the right dependencies (in this case, the entity framework context).  This means getting rid of static and adding a constructor.  I'll also modify the constructor to accept a `BloggingContext` created above (which itself will need a `DbContextOptions<BloggingContext>` injected).

```csharp
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;

namespace functions_csharp_entityframeworkcore
{
    public class HttpTrigger
    {
        private readonly BloggingContext _context;
        public HttpTrigger(BloggingContext context)
        {
            _context = context;
        }

        [FunctionName("GetPosts")]
        public async Task<IActionResult> Get(
            [HttpTrigger(AuthorizationLevel.Function, "get", Route = "posts")] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            // Code that returns posts - you can see this code by going
            // to the full sample linked at the bottom
            return new OkResult();
        }
    }
}
```

To register services like `BloggingContext`, I create a `Startup.cs` file in the project and implement the `FunctionsStartup` configuration.  Notice I use an attribute to signal to the functions host where it can run my configuration.

```csharp
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System;

[assembly: FunctionsStartup(typeof(functions_csharp_entityframeworkcore.Startup))]

namespace functions_csharp_entityframeworkcore
{
    class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            string SqlConnection = Environment.GetEnvironmentVariable("SqlConnectionString");
            builder.Services.AddDbContext<BloggingContext>(
                options => options.UseSqlServer(SqlConnection));
        }
    }
}
```

### Enable design-time DbContext creation

As mentioned, I want to use the [design-time DbContext creation](https://docs.microsoft.com/en-us/ef/core/miscellaneous/cli/dbcontext-creation).  Since I'm not using ASP.NET directly here, but implementing the Azure Functions `Configure` method, entity framework won't automatically discover the desired `DbContext`.  So I'll make sure to implement an `IDesignTimeDbContextFactory` to drive the tooling.

```csharp
public class BloggingContextFactory : IDesignTimeDbContextFactory<BloggingContext>
{
    public BloggingContext CreateDbContext(string[] args)
    {
        var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
        optionsBuilder.UseSqlServer(Environment.GetEnvironmentVariable("SqlConnectionString"));

        return new BloggingContext(optionsBuilder.Options);
    }
}
```

### Getting the project .dll in the right spot

There's one last thing I need to do.  When you build an Azure Functions project, `Microsoft.NET.Sdk.Functions` does some organizing of the build artifacts to create a valid function project structure.  One of the .dlls it moves to a sub-folder is the project .dll.  Unfortunately, for the design-time tools like entity framework migration, it expects the .dll to be at the root of the build target.  So to make sure both tools are happy, I'll add a quick post-build event to copy the .dll to the root as well.  I added this to my `.csproj` file for the project.

```xml
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
  <Exec Command="copy /Y &quot;$(TargetDir)bin\$(ProjectName).dll&quot; &quot;$(TargetDir)$(ProjectName).dll&quot;" />
</Target>
```

## Adding an entity framework migration

I went into the Azure Portal and created a simple Azure SQL database.  I copied the connection string into the `local.settings.json` file with a new value for `SqlConnectionString`.  You can see in my previous code samples I used that as the environment variable that would have the connection string.  This way I don't have to check it into source control 🥽. 

To make sure the connection string is also available to the CLI tooling for migrations, I'll open my Package Manager Console and set the environment variable before adding a migration and updating the database.

```powershell
$env:SqlConnectionString="Server=tcp:mySqlServerStuffxxx"
Add-Migration InitialCreate
Update-Database
```

When browsing to the SQL database in the Azure Portal, I can see the tables were successfully created!

![Post create tables create](https://i.imgur.com/PyDkh1p.png)

## Writing the function app and publishing

That's all the heavy lifting.  Now I just write a few simple HTTP triggered functions that can return and add data to the `BloggerContext` I injected in.  When running the app, I can then call the different `GET` and `PUT` methods to validate data is being persisted and returned correctly.

After publishing, I just make sure to set the appropriate application setting for `SqlConnectionString` with my production SQL connection string, and we're in business!

You can see the full project code [on my GitHub account](https://github.com/jeffhollan/functions-csharp-entityframeworkcore)