如何将dbContext注入iLogger

时间:2019-10-19 16:15:36

标签: c# asp.net asp.net-mvc web-services dependency-injection

我试图将ApplicationDbcontext注入iLogger。

当我在_context variableCustomLoggerProvider中使用CustomLoggerExtension时,这是工作

当软件CreateLogger创建CustomLogger的实例时,ApplicationDbContext遇到了问题,当我使用_context变量访问数据库时,应用程序崩溃了和无效

以下是错误日志:

  

System.ObjectDisposedException HResult = 0x80131622 Messaggio =无法   访问已处置的对象。导致此错误的常见原因是处理   依赖注入解决的上下文,然后再进行   尝试在应用程序的其他位置使用相同的上下文实例。   如果在上下文上调用Dispose(),则可能会发生这种情况,或者   将上下文包装在using语句中。如果您使用依赖项   注入,您应该让依赖注入容器保重   处理上下文实例的方法。

     

Origine = Microsoft.EntityFrameworkCore Analisi dello堆栈:在   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和状态)

我认为这是服务生命周期的问题。

有人知道解决方案吗?

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
    }
}

0 个答案:

没有答案