Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: ASP Core 3 MVC | BackgroundService - Mazanie záznamov z databáze

Aktivity
Avatar
Tadeáš Burda
Brigádník
Avatar
Tadeáš Burda :8.5.2020 13:44

Toto chcem aby sa vykonávalo:

public class OneTimeMessageCollector : BackgroundService
    {
        private readonly ApplicationDbContext _context;



        public OneTimeMessageCollector(ApplicationDbContext context)
        {
            _context = context;
        }


        /// <summary>
        /// Odstráň staré správy ak sú staršie ako stanovený počet dní
        /// </summary>
        /// <param name="numberDay">Počet dní</param>
        private void RemoveOldMessages(int numberDay)
        {
            // Nájdi správy
            TimeSpan time = new TimeSpan(numberDay, 0, 0, 0);
            OTmessage[] messages = _context.OTmessages.Where(m => (DateTime.Now - m.CreateDay) <= time).ToArray();

            // Odstráň správy
            if(messages != null && messages.Length > 0)
            {
                _context.OTmessages.RemoveRange(messages);
                _context.SaveChanges();
            }
        }



        protected async override Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                RemoveOldMessages(1);
                await Task.Delay(new TimeSpan(1, 0, 0, 0), stoppingToken);
            }
        }
    }

ConfigureServi­ces:

services.AddScoped<OneTimeMessageCollector>();
services.AddHostedService<OneTimeMessageCollector>();

Error:

System.AggregateException
  HResult=0x80131500
  Message=Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: MyWeb.Classes.OneTimeMessageCollector': Cannot consume scoped service 'MyWeb.Data.ApplicationDbContext' from singleton 'Microsoft.Extensions.Hosting.IHostedService'.)
  Source=Microsoft.Extensions.DependencyInjection
  StackTrace:
   at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(IEnumerable`1 serviceDescriptors, ServiceProviderOptions options)
   at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options)
   at Microsoft.Extensions.DependencyInjection.DefaultServiceProviderFactory.CreateServiceProvider(IServiceCollection containerBuilder)
   at Microsoft.Extensions.Hosting.Internal.ServiceFactoryAdapter`1.CreateServiceProvider(Object containerBuilder)
   at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider()
   at Microsoft.Extensions.Hosting.HostBuilder.Build()
   at MyWeb.Program.Main(String[] args) in C:\Users\tadea\source\repos\MyWeb\MyWeb\Program.cs:line 10

  This exception was originally thrown at this call stack:
    [External Code]

Inner Exception 1:
InvalidOperationException: Error while validating the service descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: MyWeb.Classes.OneTimeMessageCollector': Cannot consume scoped service 'MyWeb.Data.ApplicationDbContext' from singleton 'Microsoft.Extensions.Hosting.IHostedService'.

Inner Exception 2:
InvalidOperationException: Cannot consume scoped service 'MyWeb.Data.ApplicationDbContext' from singleton 'Microsoft.Extensions.Hosting.IHostedService'.

Zkusil jsem: Chápem kde je chyba, ale nedokážem to fixnúť tak abych mohel využiť DI ApplicationDbCon­text. Rozmýšlal sem že bych nevyužil DI ale vytvoril instancii ApplicationDbCon­text, ale rači bych využil DI ak to ide. Nechápem, ale presne ako to funguje, teprva to skúšam. Ide mi to v poho ak nevyužijem DI, ale ak sa to snažím implementovat tak to nezkompiluje.

Chci docílit: V db mám záznamy ktoré bych chcel mazať ak sú staršie než stanovený počet dní. Tady mi poradily použiť BackgroundService, což mi vyhovuje. SKukel sem niake tutoriale a dokumentáciu ktoru chapem dovtedy pokial nemusim využiť DI. Rad bych mal len jednu instanci ApplicationDbCon­text, ale potom už nechápem temu ako to fixnut. Tak keby niekto mal čas a vysvetlil mi kde robím chybu. Dik

 
Odpovědět
8.5.2020 13:44
Avatar
Mirek Slouka
Člen
Avatar
Odpovídá na Tadeáš Burda
Mirek Slouka:9.5.2020 13:51

Ahoj, trochu jsem upravil tvou třídu.

public class OneTimeMessageCollector : BackgroundService
    {
        private readonly IServiceProvider serviceProvider;

        public OneTimeMessageCollector(IServiceProvider serviceProvider)
        {
            this.serviceProvider = serviceProvider;
        }

        public void RemoveOldMessages(int numberDay)
        {
            using (var scope = serviceProvider.CreateScope())
            {
                var _context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
                TimeSpan time = new TimeSpan(numberDay, 0, 0, 0);
                OTmessage[] messages = _context.OTmessages.Where(m => (DateTime.Now - m.CreateDay) <= time).ToArray();

                // Odstráň správy
                if (messages != null && messages.Length > 0)
                {
                    _context.OTmessages.RemoveRange(messages);
                    _context.SaveChanges();
                }
            }
        }

        protected async override Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                RemoveOldMessages(1);
                await Task.Delay(new TimeSpan(1, 0, 0, 0), stoppingToken);
            }
        }
    }

ApplicationDbCon­text nepředávám přímo v constructoru, ale pomocí DI si posunu IServiceProvider, z kterého si následně v RemoveOldMessages z contextu vytáhnu ApplicationDbCon­text. Nevím proč to nejde předat přímo, ale takhle to funguje :D

Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
9.5.2020 13:51
I can explain it to you, but I can't understand it for you.
Avatar
Mirek Slouka
Člen
Avatar
Odpovídá na Tadeáš Burda
Mirek Slouka:9.5.2020 14:15

Podle všeho to na přímo ani nepůjde.
https://stackoverflow.com/…cy-injection

Nahoru Odpovědět
9.5.2020 14:15
I can explain it to you, but I can't understand it for you.
Avatar
Tadeáš Burda
Brigádník
Avatar
Odpovídá na Mirek Slouka
Tadeáš Burda :9.5.2020 16:07

Kááááámo fakt moc dík!!! Skušal sem to odrána a neslo mi to vúbec. Vcil fest uz jo! (*_*) 8-) Fakt moc dik..

 
Nahoru Odpovědět
9.5.2020 16:07
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 4 zpráv z 4.