Как сделать правильное время жизни ApplicationDbContext

когда я выполняю метод, после выполнения внешнего запроса HttpClient срок моей жизни ApplicationDbContext заканчивается, как правильно сделать этот метод?

Метод

    public async Task ConfirmEmail(int userId, Guid codeFromUser)
    {
        var user = _accountAccessor.GetUserById(userId);
        
        if (user.EmailConfirmed) throw new BadRequestException("Email already verified");

        // Getting Confirmation Code        
        var confirmationCode = await ResponseHelper.GetResponseAsync(_httpClientFactory, $"{ServiceUrlVariables.ConfirmationCodeApi}/GetCodeByUserId/{userId}");
        var confirmationCodeDto = await ResponseHelper.DeserializeResponseAsync<ConfirmationCodeDto>(confirmationCode);

        // validation
        if (confirmationCodeDto.ExpiresAt < DateTime.UtcNow) throw new BadRequestException("Code expired");
        if (confirmationCodeDto.Code != codeFromUser) throw new BadRequestException("Your code is wrong");
        
        // setting `EmailConfirmed == true`
        user.EmailConfirmed = true;
        _accountAccessor.UpdateUser(user);

        var codeId = confirmationCodeDto.Id;
        // Deleting ConfirmationCode from Db, cuz it's already verified
        await ResponseHelper.DeleteResponseAsync(_httpClientFactory, $"{ServiceUrlVariables.ConfirmationCodeApi}/DeleteConfirmationCodeById/{codeId}");
    }

ResponseHelper

// Get
    public static async Task<HttpResponseMessage> GetResponseAsync(IHttpClientFactory httpClientFactory, string requestUri)
    {
        using var client = httpClientFactory.CreateClient();
        var response = await client.GetAsync(requestUri).ConfigureAwait(false);
        
        response.EnsureSuccessStatusCode();
        
        return response;
    }

// Delete
    public static async Task DeleteResponseAsync(IHttpClientFactory httpClientFactory, string requestUri)
    {
        using var client = httpClientFactory.CreateClient();
        var response = await client.DeleteAsync(requestUri).ConfigureAwait(false);
        
        response.EnsureSuccessStatusCode();
    }

Программа

builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseNpgsql(
    ConnectionStringsVariables.BookShopDB
));

Я новичок, и мне немного сложно понять, как исправить такие ошибки.

Если я правильно понимаю, асинхронный запрос выходит за рамки моего контекста базы данных.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

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

Программа.cs

builder.Services.AddDbContext<AppDbContext>(options => options.UseNpgsql("Host=localhost;Database=example;Username=user;Password=pwd"));
builder.Services.AddScoped<UserService>();
builder.Services.AddScoped<ConfirmEmailService>();
builder.Services.AddHttpClient();

Вот как я внедрил ConfirmEmailService. Вот сервис

public class ConfirmEmailService
{
    private readonly UserService _userService;
    private readonly IHttpClientFactory _httpClientFactory;

    public ConfirmEmailService(UserService userService, IHttpClientFactory httpClientFactory)
    {
        _userService = userService;
        _httpClientFactory = httpClientFactory;
    }

    public async Task ConfirmEmailAsync(int userId, Guid codeFromUser, CancellationToken cancellationToken)
    {
        var user = await _userService.GetUserById(userId, cancellationToken);
        
        if (user.EmailConfirmed) throw new Exception("Email already verified");

        // Getting Confirmation Code        
        var confirmationCode = await ResponseHelper.GetResponseAsync(_httpClientFactory, $"http://localhost:5151/code?userId = {userId}");
        var confirmationCodeDto = await ResponseHelper.DeserializeResponseAsync<ConfirmationCodeDto>(confirmationCode);

        // validation
        if (confirmationCodeDto.ExpiresAt < DateTime.UtcNow) throw new Exception("Code expired");
        if (confirmationCodeDto.Code != codeFromUser) throw new Exception("Your code is wrong");
        
        // setting `EmailConfirmed == true`
        user.EmailConfirmed = true;
        await _userService.UpdateUser(user, cancellationToken);

        var userSaved = await _userService.GetUserById(userId, cancellationToken);

        if (userSaved.EmailConfirmed != true)
            throw new Exception("Not saved correctly");
        
        // var codeId = confirmationCodeDto.Id;
        // Deleting ConfirmationCode from Db, cuz it's already verified
        // await ResponseHelper.DeleteResponseAsync(_httpClientFactory, $"{ServiceUrlVariables.ConfirmationCodeApi}/DeleteConfirmationCodeById/{codeId}");
    }
}

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

объекты одинаковы для данного запроса, но различаются для каждого нового запрос

Если вы правильно дождались всех асинхронных вызовов, у вас не должно возникнуть проблем с обновлением базы данных после этого.

Подробнее об асинхронном программировании.

спасибо за ответ :) насколько я понимаю, проблема в том, что мне нужно синхронизировать этот http-запрос, потому что мне нужно получить ответ и после этого двигаться дальше. Как вы думаете?

Andrey341 02.05.2024 23:38

Ну, это не должно быть проблемой. Вы можете выполнить асинхронный вызов и продолжить работу после этого. Могу я посмотреть, как поживает ваш класс ResponseHelper?

doug 03.05.2024 00:11

@ Andrey341 Andrey341 Я попытался смоделировать здесь ваш сценарий и отредактировал свой ответ с учетом полученных результатов. Проверьте, помогает ли это вам.

doug 03.05.2024 19:28

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