Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Jason 16 posts 166 karma points
    22 days ago
    Jason
    0

    Dependency Injection in MigrationPlan using Composer and Component

    I am creating a custom Umbraco MigrationPlan using a Composer and Component method as outlined in this article:

    https://cornehoskam.com/posts/how-to-create-run-migrations-umbraco-v10

    This allows me to automatically upgrade my document types and content to match changes for a particular application release, e.g. new properties, migrating data, etc.

    So, I have created a migration step with the following code:

    public class Cms0001(
        IMigrationContext context,
        IContentService contentService,
        IArticleService articleService
        ) : MigrationBase(context)
    {
        private readonly IContentService _contentService = contentService;
        private readonly IArticleService _articleService = articleService;
    
        protected override void Migrate()
        {
            var articles = _articleService.GetArticles();
            ...
        }
    }
    

    When I inject the IArticleService dependency then the migration just doesn't work and no exception is generated. In debug, I can see that the Upgrader is executing the MigrationPlan but the Migrate method in this individual migration step is not being called.

    When I remove the IArticleService injection then the Migrate method is being called correctly, so it's an issue with injecting that article service into the migration step.

    The article service is being registered as follows:

    services.AddScoped<IArticleService, ArticleService>();
    

    When I change this to AddSingleton, then the Migrate method is being called with the injected article service but then I have to make the EF ApplicationDBContext a singleton and that's not advisable.

    But, even when I make this all singleton, the call to the article service fails without an error when executing the migration plan, so that doesn't seem to be the solution either.

  • Nik 1598 posts 7177 karma points MVP 6x c-trib
    22 days ago
    Nik
    0

    Hi Jason,

    What happens if you register IArticleService as Transient rather than Scoped? I can't entirely recall what the different levels are (well more importantly their order).

    Additionally, it might not be possible to inject it in the way you are, you might need to inject in the IServiceProvider (I think that's it's name) class which is the DI container, and use that to resolve the specific service during the method call not the constructor call. I had to do this to access the IPublishedContentQuery in some custom code in the past.

    Thanks

    Nik

  • Jason 16 posts 166 karma points
    21 days ago
    Jason
    0

    I tried registering the service as Transient but it still failed to enter the Migrate method so I assume it can't inject the service.

    I also tried injecting IServiceProvider and then getting the ArticleService directly but it fails with an exception "Cannot resolve scoped service from root provider".

    I have managed to get it working using Singleton but then I have to setup the EF DBContext as Singleton too and that is apparently a very bad idea for an ASP.NET application.

  • Jason 16 posts 166 karma points
    21 days ago
    Jason
    100

    I got it working by injecting the IServiceProvider, creating a scope, and then obtaining the service directly:

        var scope = _serviceProvider.CreateScope();
        var articleService = scope.ServiceProvider.GetRequiredService<IArticleService>();
    

    I guess the Umbraco migration is a singleton which is why I couldn't inject the scoped service into my migration step, so once I created a scope in the migration step, then I was able to resolve the scoped service.

Please Sign in or register to post replies

Write your reply to:

Draft