I've got a table of products plans and subscriptions in my application, and I have created a PaypalSyncService with methods to sync these tables with tables from the Paypal API.
public class PaypalSyncService
{
private readonly EzGigDbContext _context;
private readonly PaypalService _paypalService;
public PaypalSyncService(EzGigDbContext context, PaypalService paypalService)
{
_context = context;
_paypalService = paypalService;
}
public async Task Sync()
{
await SyncProducts();
await SyncPlans();
await SyncSubscriptions();
}
// other methods
}
I then created a PaypalHostedService to run those sync operations once an hour
public class PaypalSyncHostedService : IHostedService, IDisposable
{
private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly PaypalSyncService _paypalSyncService;
private Timer _timer;
//private readonly ILogger<PaypalSyncHostedService> _logger;
public PaypalSyncHostedService(PaypalSyncService paypalSyncService, IServiceScopeFactory serviceScopeFactory/*, ILogger<PaypalSyncHostedService> logger*/)
{
_paypalSyncService = paypalSyncService;
_serviceScopeFactory = serviceScopeFactory;
//_logger = logger;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_timer = new Timer(DoSync, null, TimeSpan.Zero, TimeSpan.FromHours(1));
return Task.CompletedTask;
}
private void DoSync(object state)
{
try
{
using (var scope = _serviceScopeFactory.CreateScope())
{
var paypalSyncService = scope.ServiceProvider.GetRequiredService<PaypalSyncService>();
paypalSyncService.Sync().Wait();
}
}
catch (Exception ex)
{
//_logger.LogError(ex, "Error occurred while syncing with Paypal");
}
}
public Task StopAsync(CancellationToken cancellationToken)
{
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose()
{
_timer?.Dispose();
}
}
But when I add the PaypalHostedService to my list of services in Startup.cs (ConfigureServices)
services.AddScoped<EzGigDbContext>();
services.AddScoped<ShiftService>();
services.AddScoped<PaypalService>();
services.AddScoped<OrganisationService>();
services.AddScoped<LoginService>();
services.AddScoped<PaypalSyncService>();
services.AddScoped<IHostedService, PaypalSyncHostedService>();
services.AddScoped<SubscriptionManagementService>();
services.AddScoped <UserService>();
I get the following error if I have my PaypalSyncHostedService as a Scoped variable in the service
System.InvalidOperationException
HResult=0x80131509
Message=Cannot resolve scoped service 'System.Collections.Generic.IEnumerable`1[Microsoft.Extensions.Hosting.IHostedService]' from root provider.
Source=Microsoft.Extensions.DependencyInjection
StackTrace:
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.ValidateResolution(Type serviceType, IServiceScope scope, IServiceScope rootScope)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.Microsoft.Extensions.DependencyInjection.ServiceLookup.IServiceProviderEngineCallback.OnResolve(Type serviceType, IServiceScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
at Microsoft.Extensions.Hosting.Internal.Host.<StartAsync>d__9.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.<RunAsync>d__4.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.<RunAsync>d__4.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host)
at EzGig.Program.Main(String[] args) in C:\Users\johnm\source\repos\EzGig\Program.cs:line 14
This exception was originally thrown at this call stack:
[External Code]
EzGig.Program.Main(string[]) in Program.cs
and if I try to change the PaypalHostedService to a Singleton, I get the following 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: EzGig.Services.PaypalSyncHostedService': Cannot consume scoped service 'EzGig.Services.PaypalSyncService' from singleton 'Microsoft.Extensions.Hosting.IHostedService'.)
Source=Microsoft.Extensions.DependencyInjection
StackTrace:
at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(IEnumerable`1 serviceDescriptors, IServiceProviderEngine engine, 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 EzGig.Program.Main(String[] args) in C:\Users\johnm\source\repos\EzGig\Program.cs:line 14
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: EzGig.Services.PaypalSyncHostedService': Cannot consume scoped service 'EzGig.Services.PaypalSyncService' from singleton 'Microsoft.Extensions.Hosting.IHostedService'.
Inner Exception 2:
InvalidOperationException: Cannot consume scoped service 'EzGig.Services.PaypalSyncService' from singleton 'Microsoft.Extensions.Hosting.IHostedService'.
I've tried both services as singleton, but that also threw an error. Could anyone point me in the right direction?