Почему мой EF Core DbContext не связан DI?
У меня есть приложение-функция Azure с функцией, которая запускается по триггеру BLOB-объектов. Я доказал, что эта функция может запускаться через портал Azure и реагирует на этот триггер большого двоичного объекта без проблем... или, по крайней мере, так и было.
Теперь, когда я добавил функциональность, которая использует EF Core (2.2.4), он дает мне следующую ошибку, как при локальной отладке, так и при публикации в Azure:
Microsoft.Azure.WebJobs.Host: Ошибка индексации метода "ParseThings". Microsoft.Azure.WebJobs.Host: невозможно связать параметр context с типом AvastusContext. Убедитесь, что параметр Type поддерживается привязкой. Если вы используете привязки расширений (например, хранилище Azure, ServiceBus, таймеры и т. Д.), Убедитесь, что вы вызвали метод регистрации расширений в своем коде запуска (например, builder.AddAzureStorage(), builder.AddServiceBus(), builder.AddTimers() и т. д.).
у меня есть Startup
Класс, как указано в документации Azure Function App здесь, и следуют их примеру до буквы, кроме следующей строки вместо их настроенных примеров служб:
[assembly: FunctionsStartup(typeof(AvstFunctionApp.Startup))]
namespace AvstFunctionApp
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddDbContext<AvastusContext>(options => options.UseSqlServer(Environment.GetEnvironmentVariable("AvastusDb")));
}
}
}
И начало моей функции:
public static class ParseThings
{
[FunctionName("ParseThings")]
public static void Run([BlobTrigger("summaries/{name}", Connection = "StorageConnectionString")]Stream myBlob, string name, ILogger log, AvastusContext context)
Я могу подтвердить, что AddDbContext
Линия получает удар в отладчике, так что, возможно, за кулисами происходит какая-то ошибка, или я делаю что-то невероятно глупое.
Вещи, которые я пробовал, которые не сработали, включают в себя:
- Добавление
.BuildServiceProvider(true)
кAddDbContext
линия - С помощью
WebJobsStartup
вместо недавно объявленнойFunctionsStartup
- Переход на.NET Core 2.2.0
- Изменение класса Function и
Run
метод от статического к экземпляру - Исправление некорректного пространства имен введенного
AvastusContext
Стоит также отметить, что в этом проекте Function App есть две другие функции, у которых, похоже, нет серьезных проблем, и я смог заставить работать инъекцию зависимостей, используя аналогичный метод с EF Core для другого (ASP.NET Core MVC) проект в этом решении.
Заранее благодарю за любую помощь, которую может оказать каждый!
PS Я нахожу невероятно странным, что в более поздних версиях.NET Core, приложений-функций Azure и EF Core более поздних версий не было ничего описывающего эту ситуацию, что наводит меня на мысль, что это может быть простой ошибкой. Надеюсь, что нет.
2 ответа
Возможно , вы можете попробовать внедрить IServiceProvider в свою функцию вместо AvastusContext, как я ввел в класс репозитория ниже:
private readonly IServiceProvider serviceProvider;
public SomeRepository(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
using var context = this.serviceProvider.GetService<XYZDBContext>();
Это предоставит вам объект контекста. Кроме того, не уверен, почему вы пытаетесь получить доступ к контексту в функции напрямую, для хорошей практики определите класс контекста и поддерживайте репозиторий для выполнения любых операций CRUD в коде.
Startup.cs вы можете добавить дополнительные конфигурации, например:
builder.Services.AddDbContext<XYZDBContext>(
options =>
{
options.UseSqlServer(
conn,
sqlServerOptionsAction:
sqlOptions =>
{
sqlOptions.EnableRetryOnFailure(maxRetryCount: 3, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
});
}, ServiceLifetime.Transient);
эта конфигурация отлично работает в моем текущем решении. Попробуйте это.
Приложение-функция не может разрешать dbcontext в функциях, поскольку оно может разрешать только BindingContext. Вам необходимо создать пользовательские привязки для использования dbcontext непосредственно в приложении-функции.
Другой способ получить dbcontext, введенный через DI, - передать его конструктору и использовать переменную уровня класса в функции.
public class ParseThings
{
private AvastusContext _context;
public ParseThings(AvastusContext context){
_context = context;
}
[FunctionName("ParseThings")]
public void Run([BlobTrigger("summaries/{name}", Connection = "StorageConnectionString")]Stream myBlob, string name, ILogger log){
// use _context here
}
}
Если он по-прежнему не решается, вы можете проверить, правильно ли настроен functionsStartup.