dotnet / dotnet/efcore

AccessorExtensions.GetService method can not resolve multiple services with IEnumerable<>

Open
#31,550 6 comments 0 reactions 0 assignees View on GitHub
area-dbcontext customer-reported
Dominant language
C#
Stars
14.8k
Forks
3.4k
PR merge metrics
PR metrics pending

Description

## File a bug
[x] Please check that the documentation does not explain the behavior you are seeing.
[x] Please search in both open and closed issues to check that your bug has not already been filed.

## Description
I've developed a middleware layer for several purposes. Interestingly, while implementing and running unit tests, I discovered that the method dbContext.GetService> could not resolve services. However, when I attempted to resolve a single service with the dbContext.GetService() command, the instance was successfully resolved.

InMemory and EntityFrameworkCore packages has same behavior. Inside of DbContext instance I couldn't resolve services with IEnumerable<>.

### Example code
```C#

// Middleware interface and mock implementations
public interface ITransactionMiddleware { }
public class MockTransactionMiddleware1 : ITransactionMiddleware { }
public class MockTransactionMiddleware2 : ITransactionMiddleware { }

// MockDbContext
public class MockDbContext : DbContext
{
public DbSet Entities { get; set; }
public MockDbContext(DbContextOptions options) : base(options) { }
}

// MockEntity
public class MockEntity
{
[Key]
public long Id { get; set; }
}

// Unit test
[Fact]
public async Task Should_SaveChanges_CallMiddleware_When_AnyMiddlewareAvailable()
{
// Arrange
var services = new ServiceCollection();
IServiceProvider? serviceProvider = null;
services.AddDbContext(builder =>
{
builder.UseInMemoryDatabase("MockDatabase");
builder.UseApplicationServiceProvider(serviceProvider);
});

var mockMiddleware1 = new Mock();
var mockMiddleware2 = new Mock();

mockMiddleware1.Setup(x => x.InvokeAsync(It.IsAny(), It.IsAny(), It.IsAny()));

services.AddSingleton(mockMiddleware1.Object);
services.AddSingleton(mockMiddleware2.Object);

serviceProvider = services.BuildServiceProvider();

var dbContext = _serviceProvider.CreateScope().ServiceProvider.GetService()!;
var repository = new MockRepositoryImp(dbContext);

var entity = new MockEntity();
await repository.AddAsync(entity, default);

// Act
await repository.SaveChangesAsync(default);

// Assert
mockMiddleware1.Verify(x => x.InvokeAsync(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once);
}
```

Also when I try to resolve services from application, it worked as expected.
```C#
var middlewares1 = app.Services.GetServices();
var middlewares2 = app.Services.GetService>();`
```

### Provider and version information

EF Core version: 7.0.10
Database provider: Microsoft.EntityFrameworkCore - 7.0.10
Namespace : Microsoft.EntityFrameworkCore.Infrastructure;
Target frameworks: .NET 6.0/NET7.0
Operating system: Windows 11 Pro
IDE: Microsoft Visual Studio Community 2022 (64-bit) - Current Version 17.6.1

![Screenshot 2023-08-25 085511](https://github.com/dotnet/efcore/assets/18365191/1b887a31-c6d4-4d89-baa6-285d458e3c19)
![Screenshot 2023-08-25 085618](https://github.com/dotnet/efcore/assets/18365191/cc5d612f-cb01-4ea6-ba38-d45f1b444615)
![Screenshot 2023-08-25 085650](https://github.com/dotnet/efcore/assets/18365191/88887d70-6882-4d21-ae05-2687886b1f95)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.