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

Scoped Services Instantiated Multiple Times on Single Function Run #15

Closed
ScotlandBard opened this issue May 24, 2019 · 2 comments
Closed

Comments

@ScotlandBard
Copy link

ScotlandBard commented May 24, 2019

When registering a scoped service with an implementationFactory set, multiple instances of the service are being created per run of a function. To recreate this issue, I used the following Startup in a sample project:

using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Services;
using System;
using System.Collections.Generic;
using System.Text;

[assembly: FunctionsStartup(typeof(CakeOrdersFunctions.Startup))]
namespace CakeOrdersFunctions
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddScoped<ISupplier, Supplier>();
            builder.Services.AddScoped<IStoreFront>(x => new StoreFront());
            builder.Services.AddScoped<IBakery, Bakery>();

            //Ingredients/registers added in the ISupplier/IStoreFront services will not be reflected in this service:
            builder.Services.AddScoped<IManualBakery>(x => new ManualBakery(x.GetRequiredService<ISupplier>(), x.GetRequiredService<IStoreFront>()));
        }
    }
}

Azure Function Code

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using Services;
using System.Threading.Tasks;

namespace CakeOrdersFunctions
{
    public class SetupBakery
    {
        public readonly IStoreFront _storeFront;
        public readonly ISupplier _supplier;
        public readonly IBakery _bakery;
        public readonly IManualBakery _manualBakery;

        public SetupBakery(IStoreFront storeFront,
            ISupplier supplier,
            IBakery bakery,
            IManualBakery manualBakery)
        {
            _storeFront = storeFront;
            _supplier = supplier;
            _bakery = bakery;
            _manualBakery = manualBakery;
        }

        [FunctionName("SetupBakery")]
        public async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            _storeFront.AddRegister("emp1");
            _storeFront.AddRegister("emp2");

            _supplier.AddIngredient("sugar");
            _supplier.AddIngredient("love");

            var stats = new
            {
                StoreFrontRegisters = _storeFront.GetAvailableRegisters(),
                SupplierIngedients = _supplier.GetIngredientCount(),
                BakerRegisters = _bakery.GetAvailableRegisters(),
                BakeryIngredients = _bakery.GetSupplierIngredientCount(),
                ManualBakeryRegisters = _manualBakery.GetAvailableRegisters(),
                ManualBakeryIngredients = _manualBakery.GetSupplierIngredientCount()
            };

            return new OkObjectResult(stats);
        }
    }
}

Services:

public class Bakery : IBakery
    {
        private readonly ISupplier _supplier;
        private readonly IStoreFront _storeFront;

        public Bakery(ISupplier supplier, IStoreFront storeFront)
        {
            _supplier = supplier;
            _storeFront = storeFront;
        }

        public void BakeCake()
        {

        }

        public int GetSupplierIngredientCount() => _supplier.GetIngredientCount();
        public int GetAvailableRegisters() => _storeFront.GetAvailableRegisters();
    }

private readonly ISupplier _supplier;
        private readonly IStoreFront _storeFront;

        public ManualBakery(ISupplier supplier, IStoreFront storeFront)
        {
            _supplier = supplier;
            _storeFront = storeFront;
        }

        public void BakeCake()
        {

        }

        public int GetSupplierIngredientCount() => _supplier.GetIngredientCount();
        public int GetAvailableRegisters() => _storeFront.GetAvailableRegisters();

public class StoreFront : IStoreFront
    {
        private ICollection<string> _registers;

        public StoreFront()
        {
            _registers = new List<string>();
        }

        public void AddRegister(string employee)
        {
            _registers.Add(employee);
        }

        public int GetAvailableRegisters() => _registers.Count();
    }

public class Supplier : ISupplier
    {
        private ICollection<string> _availableIngredients;

        public Supplier()
        {
            _availableIngredients = new List<String>();
        }

        public void AddIngredient(string ingredient)
        {
            _availableIngredients.Add(ingredient);
        }

        public int GetIngredientCount() => _availableIngredients.Count();
    }

Results (all values should be 2):

{
    "storeFrontRegisters": 2,
    "supplierIngedients": 2,
    
//builder.Services.AddScoped<IBakery, Bakery>();
    "bakeryRegisters": 2,
    "bakeryIngredients": 2,
	
//builder.Services.AddScoped<IManualBakery>(x => new ManualBakery(x.GetRequiredService<ISupplier>(), x.GetRequiredService<IStoreFront>()));
    "manualBakeryRegisters": 0,
    "manualBakeryIngredients": 0
}

I also replicated the service registration in an ASP.NET Core project to verify that this is an Azure Functions-specific issue.

@ScotlandBard ScotlandBard changed the title Scoped Services Instantiated Multiple Times Scoped Services Instantiated Multiple Times on Single Function Run May 24, 2019
@APIWT
Copy link

APIWT commented Jun 11, 2019

I am having the same issue. Could we please get some feedback on this?

@meixger
Copy link

meixger commented Jun 11, 2019

seems related to Azure/azure-functions-host#3399

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

No branches or pull requests

3 participants