by

Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
    Alistair Evans
    @alistairjevans
    Ok, give it a try and come back if you aren't able to make it work.

    @RyannnnnnR, how is the DB context registered? Is this an Entity Framework DB Context, and if so, is it registered in Startup correctly? I.e. do you have something like this somewhere:

    public void ConfigureServices(IServiceCollection services)
    {
        // ... your other services
    
        services.AddDbContext<UserDBContext >(options =>
                options.UseSqlServer(Configuration.GetConnectionString("UserDBContext")));
    }

    ?

    RyannnnnnR
    @RyannnnnnR
    Hey @alistairjevans . Yeah I have it set up correctly in my service. I.e what you have above. The workflow I have implemented is a bit complicated. I have a class library called Common, That assembly scans for Query objects and associates them with a Handler. The problem is that these handlers need an instance of that DbContext, but since autofac is resolving all the dependencies for the handler, I need a way to register that UserDBContext in my autofac registry without having access to that UserDBContext. I hope this makes sense.
    Peter Amrehn
    @jongleur1983
    @alistairjevans see this gist for an example: https://gist.github.com/jongleur1983/5d45dd6034fc554c5f2d0a054444924d
    Peter Amrehn
    @jongleur1983
    maybe I can get something to work in OnPreparing...
    Alistair Evans
    @alistairjevans
    @RyannnnnnR; I'm not sure I entirely understand what's going on; are you able to create a gist or repo with a reproduction?
    RyannnnnnR
    @RyannnnnnR
    @alistairjevans Yeah, I have a repo. Give me one sec to push the latest stuff
    Note, these are two different services/libraries, etc
    Michael Wegge
    @Firedragonweb

    Hmmm...interesting. Can you provide the detail of the exception that get's raised?

    Sure, thank you!
    I have the following test case:

                builder.RegisterType<Root1>().Keyed<IRootService>("A");
                builder.RegisterType<Root2>().Keyed<IRootService>("B");
                builder.RegisterType<Second>().AsSelf().SingleInstance();//.InstancePerLifetimeScope();//.InstancePerOwned<IRootService>();
                IContainer container = builder.Build();
                Owned<IRootService> rootService = container.ResolveKeyed<Owned<IRootService>>("B");
                Second second = container.Resolve<Second>();
                if(ReferenceEquals(rootService.Value.Second, second))
                {
                    Debugger.Break();
                }

    If Second is registered as SingleInstance, it works and the debugger breaks. If I use InstancePerLifetimeScope, it works and the debugger breaks not (entirely correct up until here). If I use InstancePerOwned, the following exception is thrown:

    DependencyResolutionException: Unable to resolve the type 'AutofacTests.Program+Second' because the lifetime scope it belongs in can't be located. The following services are exposed by this registration:
    AutofacTests.Program+Second
    DependencyResolutionException: No scope with a tag matching 'AutofacTests.Program+IRootService' is visible from the scope in which the instance was requested.
    
    If you see this during execution of a web application, it generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario). Under the web integration always request dependencies from the dependency resolver or the request lifetime scope, never from the container itself.
    Alistair Evans
    @alistairjevans
    @Firedragonweb, I smell something weird; it's hard to track this on Gitter. Would you be able to raise an issue in the Autofac GitHub repo? Ideally, would you be able to create a reproduction repository with a failing unit test in it? It makes it a lot faster to process these sort of issues.
    Michael Wegge
    @Firedragonweb
    Sure thing, I will get to it soon. Thank you for the help!
    Alistair Evans
    @alistairjevans

    @RyannnnnnR; from what I can tell at a glance, you're registering your IDbContext implementations as their interfaces:

    builder.RegisterAssemblyTypes(ExecutingAssembly)
                .Where(t => t.IsAssignableTo<IDbContext>())
                .AsImplementedInterfaces();

    but you're resolving them from the type:

    public UserRepository(UserDBContext dbContext)
    {
            _dbContext = dbContext;
    }

    If you need to resolve as the type, you may want to change AsImplementedInterfaces() to AsSelf().

    Michael Wegge
    @Firedragonweb
    @alistairjevans I created #1094 - please let me know if that issue documents the problem enough :)
    RyannnnnnR
    @RyannnnnnR

    @alistairjevans; Thanks for the hint and it got me further! I ended up going with:

      builder.RegisterAssemblyTypes(ExecutingAssembly)
                    .Where(t => t.IsClosedTypeOf(typeof(IDbContext<>)))
                    .AsSelf()
                    .InstancePerLifetimeScope();

    Except now whenever, I try and use the injected dbcontext, I get:

    fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
          An unhandled exception has occurred while executing the request.
    System.Threading.Tasks.TaskCanceledException: A task was canceled.
       at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenDbConnectionAsync(Boolean errorsExpected, CancellationToken cancellationToken)
       at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenDbConnectionAsync(Boolean errorsExpected, CancellationToken cancellationToken)
       at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenAsync(CancellationToken cancellationToken, Boolean errorsExpected)
       at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
       at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.AsyncEnumerator.InitializeReaderAsync(DbContext _, Boolean result, CancellationToken cancellationToken)
       at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
       at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
       at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
       at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
       at UserService.Repositories.UserRepository.FindByIdAsync(String id) in /Users/ryan/Documents/invoicer-backend-microservices/src/UserService/Repositories/UserRepository.cs:line 31
       at UserService.Queries.Handlers.GetUserByIDQueryHandler.Handle(GetUserByIDQuery query) in /Users/ryanr/Documents/invoicer-backend-microservices/src/UserService/Queries/Handlers/GetUserByIDQueryHandler.cs:line 19
       at UserService.Controllers.UsersController.GetUserById(GetUserByIDQuery query) in /Users/ryanr/Documents/invoicer-backend-microservices/src/UserService/Controllers/UsersController.cs:line 43
       at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.

    It looks like the same stacktrace is happening twice? Multiple threads? Is Autofac spawning them?

    RyannnnnnR
    @RyannnnnnR
    I think the stacktrace might be showing up twice is because it's getting rethrown, probably for the DeveloperExceptionPage, but I have no idea . Also please let me know if there is a better way to achieve this generic db context pattern. Thanks again
    Sami Al Khatib
    @alsami

    @RyannnnnnR you have a sample application available? Autofac is definitely not spawning any additional threads/tasks. Furthermore, the DbContext already provides generic access using context.Set<YourEntity>().

    Also, you can simplify the registration like that I think:

     builder.RegisterAssemblyTypes(ExecutingAssembly)
                    .AsClosedTypesOf((typeof(IDbContext<>))
                    .AsSelf()
                    .InstancePerLifetimeScope();

    I think what is happening is that more than one DbContext is created. The DbContext is not thread-safe. You can use InstancePerDependency() instead. Keep in mind that this has its downsides as well. I explained them here a bit:
    https://stackoverflow.com/a/48783504/5397642

    RyannnnnnR
    @RyannnnnnR
    Hey @alsami, The sample application is here: https://github.com/RyannnnnnR/invoicer-backend-microservices/tree/master/src/UserService -- I'm going to apologise for the state of that repo, it's a bit of a mess lol. I might be able to get away with the downsides you posted with, since the repository SHOULD be the only thing the DBCOntext gets injected to. One concern I do have though, is injecting multiple IDBContext into the same services. For example, IDbContext<User> in my UserService, vs IDbContext<Another-Object>, in the same service. Is Autofac smart enough to differentiate the two? Also im not too sure how the context.Set<Entity> would work in the context of my application; I need explicit DbContext classes to override onModelCreating and OnConfiguration
    Sami Al Khatib
    @alsami
    @RyannnnnnR Yeah, Autofac should be able to handle that. The problem I think here is really the call to InstancePerLifetimeScope bc the DbContext is not thread-safe.
    Sami Al Khatib
    @alsami

    Secondly IDbContext<T> is a redundant layer of abstraction that you do not need. You don't need DbSet<T> at all. You can always use context.Set<T>() which is already generic. If you want to use the generic repository-pattern, that would make more sense.

    Also, you are creating a new IContainer for each request in Send<TCommand>. You could always use Autofac with the extension Autofac.Extensions.DependencyInjection.

    This has plenty of downsides because nothing you register with Autofac can be a singleton now for instance and also the performance suffers from building the container on each request. Instead, hook in the extension of Autofac and inject IServiceProvider if it's really necessary to create a scope.

    RyannnnnnR
    @RyannnnnnR
    Hmm not a bad idea! But this will probably be something I look at much further down the line once I can get everything working. Anyway, moving back to problem one, if InstancePerLifetimeScope is causing the problem, wouldn’t it stand to reason that InstancePerDependency, also wouldn’t work?
    Moreover, removing that IDbContext abstraction, how would I resolve the dbcontext in my autofac module?
    Sami Al Khatib
    @alsami
    I am sending you a small pull request. GIve me some minutes
    RyannnnnnR
    @RyannnnnnR
    Thank you
    Sami Al Khatib
    @alsami
    @RyannnnnnR You should have it and I think it should help you to get started.
    RyannnnnnR
    @RyannnnnnR
    Thanks again for that Pull Request @alsami! I added some comments, there is no rush on this please get around to them when you can.
    RyannnnnnR
    @RyannnnnnR
    @alsami Wow I solved that exception! The QueryHandler was processing async handle functions, synchronously. i.e no await
    Sami Al Khatib
    @alsami

    Thanks again for that Pull Request @alsami! I added some comments, there is no rush on this please get around to them when you can.

    Glad you found it. Still try to refactor the code to use one container instead of creating one on each request. :)

    Guy Lepine
    @delepster
    Since I upated Autofac from 4.9.4 to 5.1.2, I am starting to get ObjectDisposedException (Instances cannot be resolved and nested lifetimes cannot be created from this LifetimeScope as it (or one of its parent scopes) has already been disposed.) I wonder if any changes might have caused this.
    Is this the cause: autofac/Autofac#1061
    Alistair Evans
    @alistairjevans
    Yes, that's almost certainly it. It suggests that you might be disposing a parent before you dispose all the child scopes (but it's only being detected now).
    Guy Lepine
    @delepster
    ok, thx
    Guy Lepine
    @delepster
    I'm having a hard time figuring out which lifetime scope has been disposed, since I'm using autofac through dotnet core DI, would anyone have a clue where to start?
    Alistair Evans
    @alistairjevans

    Do you kick off any background tasks during a request? If a background task is still using the lifetime scope of the request after the request has finished, this may happen.

    Or, if you create a new lifetime scope (from the request scope) for a background unit-of-work pattern, and then let that continue after the request, this can happen.

    Guy Lepine
    @delepster
    I say this would be the first case, since I do not specifically create a lifetime scope and yes, background jobs occur after the request has finished. Just to be clear then, when an interface is injected in a controller's constructor and the implementation is registered as InstancePerLifetimeScope, then the lifetime scope is bound to the request duration? Would the solution then be to get injected an ILifetimeScope instance and resolve the interface's implementation?
    Guy Lepine
    @delepster
    never mind, I found the problem source. Thanks @alistairjevans for your clever insight!
    Alistair Evans
    @alistairjevans
    👍
    Albert Hives
    @ahives
    Is there a way to pass in an argument to a module during registration?
    Albert Hives
    @ahives
    User should have the ability to pass in their file name to register some objects
    Albert Hives
    @ahives
    Instead of using a module I could create a extension method that takes an argument
    Is there an Autofac way of doing this though?
    Alistair Evans
    @alistairjevans
    Well, a module is just an object you construct. Can you pass your parameters as constructor args to the module?
    Albert Hives
    @ahives
    Probably could pass as constructor params
    stevensrf11
    @stevensrf11

    Any ideas on why autofac it throwing the exception explain below in a .net core 3.1 web api application
    https://stackoverflow.com/questions/61830753/autofac-throwing-exception-in-net-core-3-1-in-web-api-when-using-versioning-and
    An exception was thrown while invoking the constructor 'Void .ctor(Microsoft.AspNetCore.Mvc.Infrastructure.IActionDescriptorCollectionProvider, Microsoft.AspNetCore.Mvc.Routing.ActionEndpointFactory)' on type 'ControllerActionEndpointDataSource'.
    at Autofac.Core.Activators.Reflection.ConstructorParameterBinding.Instantiate() at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable1 parameters)
    at Autofac.Core.Resolving.InstanceLookup.CreateInstance(IEnumerable1 parameters)

    An exception was thrown while activating Microsoft.AspNetCore.Mvc.Routing.ControllerActionEndpointDataSource.

    Autofac is throwing an exception in a .net core 3.1 web api application. The exception is thrown at start up. The application is using versioning and Route Constraint which is causing the exception. Below is the controller and method that is causing the exception:

    [ApiVersion("1.0")]
    [Route("api/[controller]")]
    [ApiController]
    [Route("api/v{version:apiVersion}/[controller]")]
    public partial class KDataServerController : KDataController
    {
    [HttpGet]
    [RequireHttps]
    [Route("{id:int:min(5):max(5)}/getconnetions/{info}", Name = "GetConnectionsRoute")]
    [HttpGet]
    public IActionResult GetConnections(long id, string info)
    //public IActionResult Get()
    {
    var monkey = new { Id = 1, Name = "Forest Monkey", version = "1.0" };
    return Ok(monkey);
    }
    }
    The exception is thrown on the endpoints.MapControllers() line of code in the Startup class:

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
    if (env.IsDevelopment())
    {
    app.UseDeveloperExceptionPage();
    }
    app.UseHttpsRedirection();
    app.UseRouting();
    app.UseAuthorization();
    app.UseEndpoints(endpoints =>
    {
    endpoints.MapControllers();
    });
    }
    Below is the stack trace showing the autofax exception:

    at Autofac.Core.Activators.Reflection.ConstructorParameterBinding.Instantiate() at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable1 parameters)
    at Autofac.Core.Resolving.InstanceLookup.CreateInstance(IEnumerable1 parameters)

    An exception was thrown while activating Microsoft.AspNetCore.Mvc.Routing.ControllerActionEndpointDataSource.

    Sami Al Khatib
    @alsami
    Is there a reason why the controller is a partial class?
    arc95
    @arc95
    Hi all
    Been on the struggle bus with that since last week