Nano Hash - криптовалюты, майнинг, программирование

Экземпляр DbContext не меняется при внедрении зависимостей

В моем приложении у меня есть API и рабочий процесс, которым нужно использовать мою базу данных. У меня есть слой репозитория, к которому обращаются оба из них. Я использую DI в своем приложении и добавляю свой dbContext в свои репозитории.

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

Поскольку у меня есть фоновый рабочий, который является синглтоном, я не смог использовать заданное по умолчанию время жизни моего dbContext. Поэтому я добавил свой dbContext как временный как в моем рабочем, так и в моем API. Я добавил instanceId в свой dbContext, который установлен в моем конструкторе.

Конструктор dbcontext:

 public CatAPIDbContext()
    {
        InstanceId = Guid.NewGuid();
        Database.EnsureCreated();
    }

Рабочие настройки сервисов:

  public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureServices((hostContext, services) =>
        {
            services.AddDbContext<CatAPIDbContext>(ServiceLifetime.Transient);
            services.AddTransient(typeof(IFeedingProfileRepository), typeof(FeedingProfileRepository));
            services.AddTransient(typeof(IFeedingTimesRepository), typeof(FeedingTimesRepository));
            services.AddTransient(typeof(IFeedHistoryRepository), typeof(FeedHistoryRepository));
            services.AddTransient(typeof(IMotorController), typeof(MotorController));
            services.AddTransient(typeof(IFoodDispenser), typeof(FoodDispenser));
            services.AddTransient(typeof(IGenericRepository<>), typeof(GenericRepository<>));
            services.AddTransient(typeof(IFeedingTimeChecker), typeof(FeedingTimeChecker));
            services.AddHostedService<Worker>();
        });

Службы настройки API:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvcCore().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
    services.AddDbContext<CatAPIDbContext>();
    services.AddTransient(typeof(IFeedingProfileRepository), typeof(FeedingProfileRepository));
    services.AddTransient(typeof(IFeedingTimesRepository), typeof(FeedingTimesRepository));
    services.AddTransient(typeof(IFeedHistoryRepository), typeof(FeedHistoryRepository));
    services.AddTransient(typeof(IMotorController), typeof(MotorController));
    services.AddTransient(typeof(IFoodDispenser), typeof(FoodDispenser));
    services.AddTransient(typeof(IGenericRepository<>), typeof(GenericRepository<>));
}

Пример общего репо:

public class GenericRepository<T> : IGenericRepository<T> where T : class
{
public CatAPIDbContext _dbContext { get; set; }
public GenericRepository(CatAPIDbContext dbContext)
{
    _dbContext = dbContext;
}

public T GetById(object id)
{
    return _dbContext.Set<T>().Find(id);
}
}

Репо, которое я использую, и не получает последний пример состояния:

 public class FeedingProfileRepository : 
GenericRepository<FeedingProfile>, IFeedingProfileRepository
{
    public FeedingProfileRepository(CatAPIDbContext dbContext) : 
base(dbContext)
    {
    }

    public FeedingProfile GetCurrentFeedingProfile()
    {
        var profile = _dbContext.FeedingProfiles
            .Include(x => x.TimesToFeedOn)
            .Where(x => x.CurrentlyActive == true).FirstOrDefault();


        if (profile == null)
        {
            return null;
        }
        if (profile.TimesToFeedOn != null)
        {
            profile.TimesToFeedOn = profile.TimesToFeedOn.OrderByDescending(x => x.Time).ToList();
        }
        return profile;

    }
}

Когда сервер вызывает FeedingProfileRepository.GetCurrentFeedingProfile(), я проверяю instanceId dbContext, и он всегда один и тот же в течение всего времени существования моего приложения. В результате данные, которые я извлекаю из dbContext, устарели и не соответствуют текущему состоянию базы данных, поскольку dbContext никогда не удаляется. Я делаю что-то неправильно?


Ответы:


1

Как я вижу в вашем коде, вы сделали dbContext Transient, и это означает, что он создается новый экземпляр каждый раз, когда они вводятся или запрашиваются:

 services.AddDbContext<CatAPIDbContext>(ServiceLifetime.Transient);

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

services.AddDbContext<CatAPIDbContext>(ServiceLifetime.Singleton);

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

 services.AddDbContext<CatAPIDbContext>(ServiceLifetime.Scoped);
30.10.2019
  • Если я правильно понимаю, dbContext должен быть очень недолговечным, поэтому я хочу воздержаться от использования одноэлементной области. Однако проблема заключается в том, что я хотел бы использовать свой dbContext в качестве ограниченного времени жизни, но я не могу, так как я использую его в своем рабочем, который является синглтоном. Я не могу добавить dbContext с заданной областью действия к моему синглтону. Вдобавок ко всему, я бы не ожидал, что временное время жизни, которое должно быть самым коротким, обновляясь при каждом вводе/запросе, никогда не изменится и всегда будет одинаковым на протяжении всего времени жизни моего приложения. 30.10.2019
  • Вы не можете использовать Scoped Service из Singleton, постарайтесь избежать этой ситуации, для получения дополнительной информации прочитайте это: dotnetcoretutorials.com/2018/03/20/ 30.10.2019
  • Я действительно читал эту статью, хотя она объясняет мою проблему, похоже, она не предлагает решения для «одноэлементной переходной ловушки». Поскольку у меня нет другого выбора, кроме как сделать мой worker одноэлементным, и я не могу добавить свой dbContext как Scoped, я чувствую, что у меня нет другого выбора, кроме как добавить его как переходный, что снова приводит меня к ловушке одноэлементного переходного процесса. Я попытался сохранить свою собственную область видимости в моем воркере, что сработало, но это значительно снизило тестируемость, поэтому я все еще ищу лучшее решение. 30.10.2019
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

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

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..