1

I have created a new FunctionApp in Visual Studio Version 16.10.0 using the template Azure Functions with .NET 5 (Isolated) and Http trigger.

enter image description here

I have then created the following files:

Blog.cs

public class Blog
{
    public int Id { get; set; }
    public string Name { get; set; }
}

ApplicationDbContext.cs

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(
        DbContextOptions<ApplicationDbContext> options) : base(options)
    {
    }

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

Program.cs

public class Program
{
    public static void Main()
    {
        var host = new HostBuilder()
            .ConfigureFunctionsWorkerDefaults()
            .ConfigureServices(services =>
            {
                var connectionString = Environment.GetEnvironmentVariable("ConnectionStrings:DefaultConnection");
                services.AddDbContext<ApplicationDbContext>(options =>
                        options.UseSqlServer(
                        connectionString,
                        sqlServerOptions => sqlServerOptions.CommandTimeout(600)));
            })
            .Build();

        host.Run();
    }
}

Function1.cs

public class Function1
{
    private readonly ApplicationDbContext _applicationDbContext;

    public Function1(ApplicationDbContext applicationDbContext)
    {
        _applicationDbContext = applicationDbContext;
    }

    [Function("Function1")]
    public HttpResponseData Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req,
        FunctionContext executionContext)
    {
        var logger = executionContext.GetLogger("Function1");
        logger.LogInformation("C# HTTP trigger function processed a request.");

        var connectionString = _applicationDbContext.Database.GetDbConnection().ConnectionString;

        var response = req.CreateResponse(HttpStatusCode.OK);
        response.Headers.Add("Content-Type", "text/plain; charset=utf-8");

        response.WriteString("Welcome to Azure Functions!");

        return response;
    }
}

local.settings.json:

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=FunctionApp1.Test;Trusted_Connection=True;MultipleActiveResultSets=true"
  },
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"
  }
}

host.json

{
    "version": "2.0",
    "logging": {
        "applicationInsights": {
            "samplingSettings": {
                "isEnabled": true,
                "excludedTypes": "Request"
            }
        }
    }
}

I have verified that dependency injection works from Program.cs -> new HostBuilder

enter image description here

If I run Add-Migration InitialCreate in Package Manager Console I get the following error:

Unable to create an object of type 'ApplicationDbContext'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728

https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/?tabs=vs

https://learn.microsoft.com/en-us/ef/core/cli/dbcontext-creation?tabs=vs

To obtain the DbContext object from the application's service provider the example code looks like this:

public class Program
{
    public static void Main(string[] args)
        => CreateHostBuilder(args).Build().Run();

    // EF Core uses this method at design time to access the DbContext
    public static IHostBuilder CreateHostBuilder(string[] args)
        => Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(
                webBuilder => webBuilder.UseStartup<Startup>());
}

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
        => services.AddDbContext<ApplicationDbContext>();

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
    }
}

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }
}

The tools first try to obtain the service provider by invoking Program.CreateHostBuilder(), calling Build(), then accessing the Services property.

Is there anyway to make Tools work with HostBuilder instead?

Ogglas
  • 62,132
  • 37
  • 328
  • 418

2 Answers2

0

You can create a design time dbcontext, yes

https://learn.microsoft.com/en-us/ef/core/cli/dbcontext-creation?tabs=dotnet-core-cli

ErikEJ
  • 40,951
  • 5
  • 75
  • 115
  • Yes of course but passing a connection string between different environments becomes harder. If there was a way to integrate with `HostBuilder` I would prefer it. The solution below works good for Console Applications and similar but not Azure Functions using Environment Variables. https://stackoverflow.com/a/52418717/3850405 – Ogglas Jun 04 '21 at 10:07
0

I had similar issue for few days now. I just watched your solution and it helped me a lot. But I didn't create a StartUp class to add database context

public static IHostBuilder CreateHostBuilder(string[] args)
        => new HostBuilder()
        .ConfigureFunctionsWorkerDefaults()
        .ConfigureServices(service => ConfigureServices(service));

Inside ConfigureServices i just have :

services.AddDbContext<ApplicationDbContext>();

and it works.

J.Memisevic
  • 429
  • 4
  • 11