Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IImageProviders created as singletons? #52

Closed
vyliniem opened this issue Jan 22, 2019 · 5 comments
Closed

IImageProviders created as singletons? #52

vyliniem opened this issue Jan 22, 2019 · 5 comments
Assignees
Labels

Comments

@vyliniem
Copy link

Looks like I cannot inject an EF Core context into an IImageProvider as the lifecycles are not compatible:

System.InvalidOperationException: Cannot consume scoped service 'MyWebApp.Data.ApplicationDbContext' from singleton 'SixLabors.ImageSharp.Web.Providers.IImageProvider'.

I was trying to implement a provider and resolver to display images by id/guid and need to access the database to fetch the actual storage location. But seems it is not possible atm, or am I missing something?

@JimBobSquarePants
Copy link
Member

Hi @vyliniem

Yeah, that's a bit of a pickle for you. The reason we do that is to ensure that we do not want to instantiate complex members on each requests. For example in this Azure Blob Provider we take advantage of the singleton scoping to reuse the CloudBlobClient. This dramatically reduces the overhead for us.

CloudBlobClient client = this.storageAccount.CreateCloudBlobClient();

One workaround you could do for now is to use the service locator (not great but will work) inside your custom provider to return the DbContext.

In the interim I'm going to have a look to see If I can refactor this to scope the providers (cache also) to the request scope to allow more flexibility of injection but keep the performance by injecting singleton configuration types.

@sebastienros Would changing the scope upset things in Orchard or would that be ok?

@ThomasSkyldahl
Copy link

ThomasSkyldahl commented Feb 25, 2019

@vyliniem just for reference you could look at this section in the .net core docs: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.2#call-services-from-main

You could inject the IServiceScopeFactory into your IImageProvider and create a scope and resolve your ApplicationDbContext inside that scope as shown in the example in the link above.

@sebastienros
Copy link
Contributor

Going scoped should never be an issue. If you need to hold state across instances the user can always create a separate instance that is registered as Singleton and resolve it in the scoped service.

@JimBobSquarePants
Copy link
Member

@sebastienros Just to clarify, are you saying I should refactor the processors to allow efficient use in a scoped lifetime?

@vyliniem
Copy link
Author

vyliniem commented Apr 5, 2019

Sorry to abandon my question like this, but I solved the original issue by manually requesting the db-context (via HttpContext):

public Task<IImageResolver> GetAsync(HttpContext context)
{
    ...

    using (var dbContext = context.RequestServices.GetService<ApplicationDbContext>())
    {
        ...
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants