Как добавить dbContext в iLogger - PullRequest
       12

Как добавить dbContext в iLogger

0 голосов
/ 19 октября 2019

Я пытаюсь вставить ApplicationDbcontext в iLogger.

Когда я использую _context variable внутри CustomLoggerProvider или CustomLoggerExtension, это работа .

Когда программное обеспечение CreateLogger создает экземпляр CustomLogger, у меня возникает проблема с ApplicationDbContext, когда я использую переменную _context для доступа к базе данных, приложение вылетает, а нене работает .

Ниже приведен журнал ошибок:

System.ObjectDisposedException HResult = 0x80131622 Messaggio = Невозможно получить доступ к удаленному объекту. Распространенной причиной этой ошибки является удаление контекста, который был разрешен путем внедрения зависимости, а затем попытка использовать тот же экземпляр контекста в другом месте вашего приложения. Это может произойти, если вы вызываете Dispose () для контекста или заключаете контекст в оператор using. Если вы используете внедрение зависимостей, вы должны позволить контейнеру внедрения зависимостей позаботиться об удалении экземпляров контекста.

Origine = Microsoft.EntityFrameworkCore Стек delal Analisi: в Microsoft.EntityFrameworkCore.DbContext.CheckDisposed () в Microsoft.EntityFrameworkCore.DbContext.Add [TEntity] (сущность TEntity)
в Microsoft.EntityFrameworkCore.Internal.InternalDbSet 1.Add(TEntity entity) at Application.Services.EventLogDB.saveInDb(Cliente c) 28 at Application.Models.DbLogger.CustomLogger.Log[TState](LogLevel logLevel, EventId eventId, TState state, Exception exception, Func 3 форматера) в C: \ Users ...... \ Models \ DbLogger \ CustomLogger.cs: строка 122в Microsoft.Extensions.Logging.Logger.g__LoggerLog | 12_0 [TState] (LogLevel logLevel, EventId eventId, регистратор ILogger, исключение исключения, Func 3 formatter, List 1 & исключения, TState & state)

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

Кто-нибудь знает решение?

Startup.cs:

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
        services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
            .AddEntityFrameworkStores<ApplicationDbContext>();

        services.AddControllersWithViews();

        services.AddRazorPages();

        services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory, IServiceProvider serviceProvider)
{
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
            endpoints.MapRazorPages();
        });

        var serviceHttp = serviceProvider.GetService<IHttpContextAccessor>();
        var serviceDbContext = serviceProvider.GetService<GestionaleOfficinaContext>();

        // THIS IS METHOD THAT SHOWS THE BAD BEHAVIOUR
        // Inside logger I need of Http context service and applicationDbContext
        loggerFactory.AddCustomLogger(serviceHttp, serviceDbContext);
    }
}

CustomLogger.cs:

public static class CustomLoggerExtensions
{
    public static ILoggerFactory AddCustomLogger(this ILoggerFactory factory, IHttpContextAccessor accessor, ApplicationDbContext_context,
                                          Func<string, LogLevel, bool> filter = null)
    {
        factory.AddProvider(new CustomLogProvider(filter, accessor, _context));
        return factory;
    }
}

public class CustomLogProvider : ILoggerProvider
{
    private readonly Func<string, LogLevel, bool> _filter;
    private readonly IHttpContextAccessor _accessor;
    private readonly ApplicationDbContext_context;

    public CustomLogProvider(Func<string, LogLevel, bool> filter, IHttpContextAccessor accessor, ApplicationDbContext context)
    {
        _filter = filter;
        _accessor = accessor;
        _context = context;

        // IF I USE THE variable _context in this place of code the applicationDbContext is available
        // and so the behaviour is right

        //if (_context != null)
        //{
        //    Cliente cl = new Cliente();
        //    cl.codiceFiscale = "ALFA";
        //
        //    _context.Add(cl);
        //    _context.SaveChanges();
        //}

    }

    public ILogger CreateLogger(string categoryName)
    {
        // In this part of code there is the strange behaviour
        // _context is different by null, but when I use _context
        // the lifetime of service ApplicationDbContext is END
        if (_context != null)
        {
            Cliente cl = new Cliente();
            cl.codiceFiscale = "CCC";

            _context.Add(cl);
            _context.SaveChanges();
        }

        return new CustomLogger(categoryName, _filter, _accessor, _context);
    }

    public void Dispose()
    {
        //base.Dispose();
    }
}

// THE ERROR IS IN THIS CLASS
public class CustomLogger : ILogger
{
    private string _categoryName;
    private Func<string, LogLevel, bool> _filter;
    private readonly IHttpContextAccessor _accessor;
    private readonly GestionaleOfficinaContext _context;

    public CustomLogger(string categoryName, Func<string, LogLevel, bool> filter, IHttpContextAccessor accessor, GestionaleOfficinaContext context)
    {
        _categoryName = categoryName;
        _filter = filter;
        _accessor = accessor;
        _context = context;
    }

    public IDisposable BeginScope<TState>(TState state)
    {
        return null;
    }

    public bool IsEnabled(LogLevel logLevel)
    {
        return (_filter == null || _filter(_categoryName, logLevel));
    }

    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
    {
        if (!IsEnabled(logLevel))
        {
            return;
        }

        if (formatter == null)
        {
            throw new ArgumentNullException(nameof(formatter));
        }

        var message = formatter(state, exception);

        if (string.IsNullOrEmpty(message))
        {
            return;
        }

        message = $"{ logLevel }: {message}";
        // your implementation
    }
}
...