skip to Main Content

I have an Azure Function with a Timer Trigger, developed with C# and .NET6 using Visual Studio 2022 Pro v17.4.3.

Current goal is to get a DbContext working in this function so I can query data from the underlying postgreSQL database.

A future goal is to use dependency injection and get the DbContext instantiation out of the function code.

using System;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using MyProject.Data;
using MyProject.Repositories;

namespace QP.Overwatch.FunctionApp
{
    public class MyFunction
    {
        [FunctionName("MyFunction")]
        public async Task Run([TimerTrigger("0 * * * * *")]TimerInfo myTimer, ILogger log)
        {
            log.LogInformation($"MyFunction - executed at: {DateTime.Now}");

            var optionsBuilder = new DbContextOptionsBuilder<MyContext>().UseNpgsql(System.Environment.GetEnvironmentVariable("MyConnection"));
            var dbContext = new MyContext(optionsBuilder.Options);
            var myRepository = new MyRepository(dbContext);

            var data = await myRepository.GetAllAsync();
        }
    }
}

Before adding any of the code to setup DbContext the function ran just fine. All it did at that point was log the message about execution with a time stamp. But after adding the reference to Microsoft.EntityFrameworkCore, all of a sudden it can’t recognize the function at all. I get this error:

[2023-09-18T15:31:27.052Z] No job functions found. Try making your job classes and methods public. If you're using binding extensions (e.g. Azure Storage, ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. builder.AddAzureStorage(), builder.AddServiceBus(), builder.AddTimers(), etc.).
[2023-09-18T15:31:27.092Z] The 'Function1' function is in error: Could not load file or assembly 'Microsoft.Extensions.Logging.Abstractions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. The system cannot find the file specified.

I tried manually adding a package reference for Microsoft.Extensions.Logging.Abstractions v7.0.0.0 but the problem persists.

Why does a reference to EF Core suddenly cause the whole function to be not found?

2

Answers


  1. Chosen as BEST ANSWER

    This thread helped me find the issue.

    In my case, the timer trigger function has a dependency upon another project that references EF Core and contains my DbContext class. This project was using EF Core 7.0.2 which in turn requires Microsoft.Extensions.Logging.Abstractions, Version=7.0.0.0

    I had to downgrade to Microsoft.Extensions.Logging.Abstractions, Version=6.0.3 for everything to work with the Azure function. This required downgrading EF Core to 6.0.22. After that everything started working as usual.


  2. I used Azure SQL Database for database.

    I was also getting same error when I was using your code.

    enter image description here

    To resolve this issue, I have used .NET 6 isolated runtime and lower Version 6.0.22 for Microsoft.EntityFrameworkCore.

    Some changes I had to make based on the isolated runtime. here are all the files.

    **My Project Directory**
    - MyProject
      - Data
        - PlaceholderEntity.cs
        - MyContext.cs
      - Repositories
        - IMyRepository.cs
        - MyRepository.cs
      - Function1.cs
      - Program.cs
    

    MyContext.cs

    using Microsoft.EntityFrameworkCore;
    
    namespace MyProject.Data
    {
        public class MyContext : DbContext
        {
            public MyContext(DbContextOptions<MyContext> options) : base(options)
            {
            }
    
            public DbSet<PlaceholderEntity> PlaceholderEntities { get; set; }
    
            protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
                // Configure your entity mappings here if needed
            }
        }
    }
    

    PlaceholderEntity.cs

    namespace MyProject.Data
    {
        public class PlaceholderEntity
        {
            public int Id { get; set; }
            public string Name { get; set; }
            
        }
    }
    

    MyRepository.cs

    using MyProject.Data;
    
    namespace MyProject.Repositories
    {
        public class MyRepository : IMyRepository
        {
            public Task<List<PlaceholderEntity>> GetAllAsync()
            {
                
                return Task.FromResult(new List<PlaceholderEntity>());
            }
        }
    }
    

    IMyRepository.cs

    using MyProject.Data;
    
    namespace MyProject.Repositories
    {
        public interface IMyRepository
        {
            Task<List<PlaceholderEntity>> GetAllAsync();
            
        }
    }
    

    Function1.cs

    using Microsoft.Azure.Functions.Worker;
    using Microsoft.Extensions.Logging;
    using MyProject.Data;
    using MyProject.Repositories;
    using System;
    using System.Threading.Tasks;
    
    namespace MyProject
    {
        public class Function1
        {
            private readonly ILogger<Function1> _logger;
            private readonly IMyRepository _myRepository;
    
            public Function1(ILogger<Function1> logger, IMyRepository myRepository)
            {
                _logger = logger;
                _myRepository = myRepository;
            }
    
            [Function("Function1")]
            public async Task RunAsync([TimerTrigger("0 */5 * * * *")] MyInfo myTimer, FunctionContext context)
            {
                _logger.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
                _logger.LogInformation($"Next timer schedule at: {myTimer.ScheduleStatus.Next}");
    
                var data = await _myRepository.GetAllAsync();
            }
        }
    
        public class MyInfo
        {
            public MyScheduleStatus ScheduleStatus { get; set; }
    
            public bool IsPastDue { get; set; }
        }
    
        public class MyScheduleStatus
        {
            public DateTime Last { get; set; }
    
            public DateTime Next { get; set; }
    
            public DateTime LastUpdated { get; set; }
        }
    }
    

    Program.cs

    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    using MyProject.Data;
    using MyProject.Repositories;
    
    var host = new HostBuilder()
        .ConfigureFunctionsWorkerDefaults()
        .ConfigureServices(services =>
        {
            // Configure services here, similar to Startup.cs
            var connectionString = System.Environment.GetEnvironmentVariable("MyConnection");
            services.AddDbContext<MyContext>(options =>
                options.UseSqlServer(connectionString));
    
            services.AddScoped<IMyRepository, MyRepository>();
            })
        .Build();
    
    host.Run();
    

    MyProject.csproj

    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
        <TargetFramework>net6.0</TargetFramework>
        <AzureFunctionsVersion>v4</AzureFunctionsVersion>
        <OutputType>Exe</OutputType>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
      </PropertyGroup>
      <ItemGroup>
        <PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.19.0" />
        <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Timer" Version="4.0.1" />
        <PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.14.0" />
        <PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.22" />
        <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.22" />
      </ItemGroup>
      <ItemGroup>
        <None Update="host.json">
          <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </None>
        <None Update="local.settings.json">
          <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
          <CopyToPublishDirectory>Never</CopyToPublishDirectory>
        </None>
      </ItemGroup>
      <ItemGroup>
        <Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext" />
      </ItemGroup>
    </Project>
    

    Output:

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search