Получение строки подключения для DBContext при развертывании в Azure

Обновлено: этот вопрос был значительно реструктурирован, теперь я немного разобрался в проблеме, и это должно прояснить ситуацию.

Я следую этому руководству: https://learn.microsoft.com/en-us/azure/app-service/tutorial-dotnetcore-sqldb-app

Я развернул свое собственное многопроектное приложение, которое работает, но я не могу заставить строку подключения работать должным образом. По какой-то причине это работает, только если я жестко запрограммирую строку подключения в методе OnConfiguring моего класса DBContext. В противном случае выдает ошибку.

Вот так:

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder
        .UseSqlServer(
                "Nasty hard coded azure connection string",
                providerOptions => { providerOptions.EnableRetryOnFailure(); });
    } 

Однако, очевидно, я хочу получить строку подключения из файла конфигурации или переменной среды.

До развертывания у меня было следующее. Метод расширения для IServiceColleciton, который устанавливает строку подключения:

public static void ConfigureSqlContext(this IServiceCollection services,
    IConfiguration configuration) =>
    services.AddDbContext<PeakedDbContext>(opts =>
 opts.UseSqlServer(configuration.GetConnectionString("defaultConnection")));

то этот метод вызывается в program.cs. Вполне нормальная установка.

И я также настроил IDesignTimeDBContextFactory следующим образом:

 public class RepositoryContextFactory : IDesignTimeDbContextFactory<PeakedDbContext>
    {
        public PeakedDbContext CreateDbContext(string[] args)
        {
            var configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json")
            .Build();
            var builder = new DbContextOptionsBuilder<PeakedDbContext>()
            .UseSqlServer(configuration.GetConnectionString("defaultConnection"));
            return new PeakedDbContext(builder.Options);
        }
    }

И мой файл appsettings.json, и конфигурация службы приложений Azure имеют одно и то же имя defaultConnection.

Насколько я могу судить, этот подход рекомендуется здесь: https://learn.microsoft.com/en-us/ef/core/cli/dbcontext-creation?tabs=dotnet-core-cli

Я также попытался добавить пустой конструктор для моего DBContext. (Не уверен, как это повлияет на вещи, поскольку у меня есть другие DI в моем конструкторе DBContext. Мои конструкторы DBContext немного выходят из-под контроля:

    public PeakedDbContext()
    {
    }

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

    public PeakedDbContext(DbContextOptions options, ICurrentUserService currentUserService) : base(options)
    {
        _currentUserService = currentUserService;
    }

Согласно второй ссылке выше, мне не нужен метод OnConfiguring в моем DBContext... и даже если я это сделаю, как правильно передать доступ к configuration.GetConnectionString вместо жесткого кодирования строки подключения? Должен ли я просто добавить еще один конструктор DBContext с введенной конфигурацией? Однако это работает ТОЛЬКО, если у меня есть метод onconfiguring. Ни контекстная фабрика, ни настройка метода расширения не используются службой приложений Azure.

Разве он не должен использовать фабрику времени разработки или метод расширения конфигурации хоста, который я установил выше? Как правильно использовать _configuration.GetConnectionString("defaultConnection"), чтобы он работал как локально, так и в развертывании Azure?

Обновлять: Все равно не повезло. Я попытался добавить строку подключения к базе данных в качестве переменной среды на Azure следующим образом:

а затем обновить всю мою ссылку на строку getconnection - в program.cs, IDesignFactory и OnConfiguring - вот так:

Environment.GetEnvironmentVariable("PeakedDbConn")

Это продолжает работать локально. Но при развертывании в Azure он утверждает, что строка подключения имеет значение null... поэтому эта переменная не отображается. Я также не могу найти код, который будет получать доступ к defaultConnection из изображения. Что странно, потому что он прекрасно обращается к переменной SECRET.

Какую структуру вы используете? Пожалуйста, поделитесь своим .csproj файлом один раз.

Harshitha 25.01.2023 06:32

В Program.cs добавьте builder.Services.AddDbContext<MyDatabaseContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionStri‌​ng("MyDbConnection")‌​)); builder.Configuration.AddEnvironmentVariables(); и проверьте один раз.

Harshitha 25.01.2023 10:23

Спасибо, у меня уже есть бит AddDBContext в моем методе расширения, но я попытался добавить AddEnvVariables в program.cs и IDesignTimeFactory, это не имело никакого значения. Он по-прежнему говорит, что нет провайдера для DBContext.

Gary Frewin 25.01.2023 14:18
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
Как установить LAMP Stack 1/2 на Azure Linux VM
Как установить LAMP Stack 1/2 на Azure Linux VM
В дополнение к нашему предыдущему сообщению о намерении Azure прекратить поддержку Azure Database для MySQL в качестве единого сервера после 16...
0
3
102
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я следовал тому же коду, который вы предоставили, с небольшими изменениями.

Выполните следующие шаги, чтобы получить строку подключения из appsettings.json и переопределить значение, если Azure App Connection String было установлено.

Поскольку вы используете .NET Core 6, я установил все конфигурации в самом Program.cs.

Мой Program.cs

builder.Services.AddDbContext<MyDatabaseContext>(options =>
                    options.UseSqlServer(builder.Configuration.GetConnectionString("MyDbConnection")));
builder.Configuration.AddEnvironmentVariables();

Одно и то же имя Connection String должно существовать как в Local, так и в Azure App Connection Strings.

Мой appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "MyDbConnection": "Dummy Connection String"
  }
}

Строка подключения к приложению Azure:

  • Чтобы проверить, получаем ли мы значение Connection String, я написал код в Controller.
 private readonly IConfiguration Configuration;
 public HomeController(ILogger<HomeController> logger,IConfiguration config)
        {
            _logger = logger;
            Configuration = config;
        }
       
         public IActionResult Index()
        {
            var myconnStr = Configuration.GetConnectionString("MyDbConnection");           
            ViewBag.myconnStr = myconnStr;           
            return View();
        }

Мой .csproj файл:

<Project Sdk = "Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include = "Microsoft.EntityFrameworkCore" Version = "7.0.2" />
    <PackageReference Include = "Microsoft.EntityFrameworkCore.SqlServer" Version = "7.0.2" />
    <PackageReference Include = "Microsoft.Extensions.Configuration.AzureAppConfiguration" Version = "5.2.0" />
    <PackageReference Include = "Microsoft.Extensions.Configuration.Json" Version = "7.0.0" />
  </ItemGroup>

</Project>

Локальный вывод:

Вывод развернутого приложения:

Ответ принят как подходящий

Итак, проблема оказалась в действиях GitHub. В учебнике, которому я следовал по первой ссылке, это не упоминается, возможно, потому, что это API одного проекта... не совсем уверен.

В учебнике используются действия github для сборки и развертывания приложения, но для меня во время сборки происходит сбой, сообщающий об отсутствии строки подключения. Это связано с тем, что процесс сборки GitHub не имеет доступа ни к вашей локальной переменной, ни к переменной среды Azure.

Поэтому мне пришлось зайти в настройки моего репозитория github и щелкнуть левой кнопкой мыши секреты и переменные < действия.

Нажмите «Создать новый секрет репозитория», дайте ему то же имя, что и ваша переменная среды, например, PEAKEDDBCONN для меня. Затем присвойте ему значение. Я просто использовал свою локальную строку хоста, но я думаю, что вы можете ввести здесь «monkeynuts», если хотите, просто она не должна быть нулевой.

Затем вам нужно добавить строку в файл yaml вашего рабочего процесса, ту же самую, о которой говорится в руководстве, чтобы сообщить ему о переменной среды. Я добавил это так:

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      PEAKEDDBCONN: ${{ secrets.PEAKEDDBCONN }}

Тогда все прекрасно строится и работает.

Для всех, кому это поможет, я решил опубликовать всю эту настройку в блоге: https://garyfrewin.hashnode.dev/setting-up-an-entity-framework-core-web-api-on-azure-with-sqlserver-a-step-by-step-guide-for-hobby- проекты

Другие вопросы по теме