मैंने अपना पहला एएसपी नेट कोर शुरू किया, एक मुझे Spring Boot Application के बारे में पता है, इसलिए मैंने अपनी नई परियोजना में वह बात डालने की कोशिश की जो मुझे पता है।

मैंने अपनी सेवाओं, रिपॉजिटरी में निर्भरता इंजेक्शन लगाया। सेवा में मैंने Singleton और रिपॉजिटरी को Transient का उपयोग करके रखा, लेकिन मैं dbContext को Entity Framework द्वारा प्रबंधित करने के लिए बदल देता हूं, और त्रुटि दिखाई दी।

सबसे पहले क्योंकि सेवाओं सिंगलटन, मैंने उन्हें क्षणिक में बदल दिया, लेकिन मैंने अन्य वेब सेवा तक पहुंचने के लिए पृष्ठभूमि सेवा भी बनाई है।

लेकिन इसने मुझे त्रुटि दी:

System.InvalidOperationException: 'Cannot consume scoped service 'TelegestaoAPI.Models.VLUMINUM_TELEGESTAOContext' from singleton 'Microsoft.Extensions.Hosting.IHostedService'.'

मेरी स्टार्टअप सेवाएं इस प्रकार हैं:

    public void ConfigureServices(IServiceCollection services)
    {
        _connString = Configuration.GetConnectionString("VluminumDataBase");

        services.
            AddMvc(option => option.EnableEndpointRouting = false).
            SetCompatibilityVersion(CompatibilityVersion.Version_3_0);

        services.
            AddMvc().
            ConfigureApiBehaviorOptions(options => { options.SuppressModelStateInvalidFilter = true; }).
            SetCompatibilityVersion(CompatibilityVersion.Version_3_0);

        services.
            AddAuthentication(Microsoft.AspNetCore.Server.IIS.IISServerDefaults.AuthenticationScheme);

        services.
            Configure<IISServerOptions>(options => { options.AutomaticAuthentication = false; });

        services.
            Configure<IISOptions>(options => { options.ForwardClientCertificate = false; });

        services.
            Configure<GzipCompressionProviderOptions>(options => options.Level = System.IO.Compression.CompressionLevel.Optimal);

        services.
            AddResponseCompression(options =>
        {
            options.Providers.Add<GzipCompressionProvider>();
        });

        services.AddControllersWithViews()
            .AddNewtonsoftJson(options =>
            options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
        );

        services.
            AddMvc().
            AddJsonOptions(options =>
        {
            options.JsonSerializerOptions.IgnoreNullValues = true;
        });

        services.AddGlobalExceptionHandlerMiddleware();

        services.AddDbContext<VLUMINUM_TELEGESTAOContext>();

        services.AddHostedService<TaskLeituraService>();

        services.AddTransient<ComandoEnviadoFilter>();

        services.AddTransient<ClienteService>();
        services.AddTransient<ComandoEnviadoService>();
        services.AddTransient<FotoService>();
        services.AddTransient<LeituraService>();
        services.AddTransient<MunicipioService>();
        services.AddTransient<PontoService>();
        services.AddTransient<PosteService>();
        services.AddTransient<TipoComandoService>();
        services.AddTransient<TipoPosteService>();
        services.AddTransient<TipoComandoService>();
        services.AddTransient<UltimaLeituraService>();
        services.AddTransient<UsuarioService>();

        services.AddTransient<ClienteRepository>();
        services.AddTransient<ComandoEnviadoRepository>();
        services.AddTransient<FotoRepository>();
        services.AddTransient<LeituraRepository>();
        services.AddTransient<MunicipioRepository>();
        services.AddTransient<PontoRepository>();
        services.AddTransient<PosteRepository>();
        services.AddTransient<TipoComandoRepository>();
        services.AddTransient<TipoPosteRepository>();
        services.AddTransient<UltimaLeituraRepository>();
        services.AddTransient<UsuarioRepository>();
    }

मेरी पृष्ठभूमि सेवा:

public class TaskLeituraService : BackgroundService
{
    private readonly LeituraService _leituraService;
    private readonly ILogger<TaskLeituraService> _logger;

    public TaskLeituraService(LeituraService leituraService, ILogger<TaskLeituraService> logger)
    {
        _leituraService = leituraService;
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            stoppingToken.Register(() => _logger.LogDebug("LeituraTaskService esta parando"));
            await ExecuteTaskLeitura();
        }
    }

    private async Task ExecuteTaskLeitura()
    {
        try
        {
            _logger.LogDebug($"{DateTime.Now} - Enviando comando leitura das fotocélulas");
            await _leituraService.ExecuteTaskLeituraFotocelulaAsync();
            _logger.LogDebug($"{DateTime.Now} - Finalizando comando leitura das fotocélulas");
            await Task.Delay(TimeSpan.FromMinutes(5));
        }
        catch (Exception e)
        {
            throw e;
        }
    }
}

और यहां बताया गया है कि मैं dbContext कैसे इंजेक्ट करता हूं

public class FotoRepository : GenericRepository
{
    private readonly VLUMINUM_TELEGESTAOContext _dbContext;
    public FotoRepository(VLUMINUM_TELEGESTAOContext dbContext)
    {
        _dbContext = dbContext;
    }
}
0
Diego Macario 21 मई 2020, 14:16

2 जवाब

सबसे बढ़िया उत्तर

आप अपने HostedService में स्कोप्ड/ट्रांजिट सेवाओं को इंजेक्ट नहीं कर सकते, इसके बजाय आपको IServiceProvider इंजेक्ट करना होगा और फिर इस तरह एक स्कोप बनाना होगा:


public class TaskLeituraService : BackgroundService
{
    private readonly ILogger<TaskLeituraService> _logger;

    public ConsumeScopedServiceHostedService(IServiceProvider services, 
        ILogger<TaskLeituraService> logger)
    {
        Services = services;
        _logger = logger;
    }

    public IServiceProvider Services { get; }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        using (var scope = Services.CreateScope())
        {
            var _leituraService= 
                scope.ServiceProvider
                    .GetRequiredService<LeituraService>();
            while (!stoppingToken.IsCancellationRequested)
            {
                stoppingToken.Register(() => _logger.LogDebug("LeituraTaskService esta parando"));
                await ExecuteTaskLeitura(_leituraService);
            }
        }
        await Task.CompletedTask;
    }

    private async Task ExecuteTaskLeitura(LeituraService _leituraService)
    {
        try
        {
            _logger.LogDebug($"{DateTime.Now} - Enviando comando leitura das fotocélulas");
            await _leituraService.ExecuteTaskLeituraFotocelulaAsync();
            _logger.LogDebug($"{DateTime.Now} - Finalizando comando leitura das fotocélulas");
            await Task.Delay(TimeSpan.FromMinutes(5));
        }
        catch (Exception e)
        {
            throw e;
        }
    }
}
1
kebek 21 मई 2020, 14:52

आप या तो अपने DbContext को सिंगलटन में बदल सकते हैं:

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

संदर्भ: इकाई फ्रेमवर्क संदर्भ

या इसे हल करने के लिए अपनी पृष्ठभूमि सेवा में मैन्युअल रूप से एक दायरा बनाएं:

private readonly IServiceProvider _services { get; }

public TaskLeituraService(IServiceProvider services, ILogger<TaskLeituraService> logger)
{
    _services = services;
    _logger = logger;
}

private async Task ExecuteTaskLeitura()
{
    try
    {
        ⋮
        using (var scope = _services.CreateScope())
        {
            var leituraService = scope.ServiceProvider.GetRequiredService<LeituraService>();
            await leituraService.ExecuteTaskLeituraFotocelulaAsync();
        }
        ⋮
    }
}

संदर्भ: पृष्ठभूमि कार्य में एक दायरे वाली सेवा का उपभोग करना

नोट:

हालांकि इस तरह का दायरा मैन्युअल रूप से बनाना संभव है, लेकिन आमतौर पर इसकी अनुशंसा नहीं की जाती है:

सिंगलटन से स्कोप्ड सेवा को हल करना खतरनाक है। यह बाद के अनुरोधों को संसाधित करते समय सेवा की गलत स्थिति का कारण बन सकता है।

संदर्भ: सिंगलटन

1
crgolden 21 मई 2020, 15:28