.NET Core IServiceScopeFactory.CreateScope() vs IServiceProvider.CreateScope() extension
Solution 1
CreateScope from IServiceProvider resolve IServiceScopeFactory
and call CreateScope()
on it:
public static IServiceScope CreateScope(this IServiceProvider provider)
{
return provider.GetRequiredService<IServiceScopeFactory>().CreateScope();
}
So, as said @Evk
functionally both methods are identical
IServiceProvider
just wrapped call CreateScope()
from IServiceScopeFactory
Solution 2
From what I tested
In ASP.NET Core 5 the following code works:
[HttpGet("/Echo/{word}")]
public IActionResult EchoAndLog(string word, [FromServices] IServiceScopeFactory serviceScopeFactory)
{
var ipAddress = HttpContext.Connection.RemoteIpAddress;
// No need to wait for logging, just fire and forget
Task.Run(async () =>
{
await Task.Delay(1000);
using (var scope = serviceScopeFactory.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<LogDbContext>();
var log = new ActivityLog
{
IpAddress = ipAddress,
Endpoint = "Echo",
Parameter = word
};
context.Add(log);
await context.SaveChangesAsync();
}
});
return Ok(word);
}
Now if you change the IServiceScopeFactory
to IServiceProvider
it will NOT work:
[HttpGet("/Echo/{word}")]
public IActionResult EchoAndLog(string word, [FromServices] IServiceProvider serviceProvider)
{
var ipAddress = HttpContext.Connection.RemoteIpAddress;
// No need to wait for logging, just fire and forget
Task.Run(async () =>
{
await Task.Delay(1000);
using (var scope = serviceProvider.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<LogDbContext>();
var log = new ActivityLog
{
IpAddress = ipAddress,
Endpoint = "Echo",
Parameter = word
};
context.Add(log);
await context.SaveChangesAsync();
}
});
return Ok(word);
}
You will get the System.ObjectDisposedException
exception:
Cannot access a disposed object.
Object name: 'IServiceProvider'.
Which tells me the IServiceProvider
will live as long as the request's lifetime (scoped), but this is not the case with IServiceScopeFactory
.
Admin
Updated on January 06, 2021Comments
-
Admin over 3 years
My understanding is that when using the built in the dependency injection, a .NET Core console app will require you to create and manage all scopes yourself whereas a ASP.NET Core app will create and manage the
HttpRequest
scope by default through defined middleware(s).With ASP.NET Core, you can optionally create and manage your own scopes that by calling
CreateScope()
for when you need services that live outside of aHttpRequest
.It is clear that calling
IServiceScopeFactory.CreateScope()
will create a newIServiceScope
every time; however, does calling theIServiceProvider.CreateScope()
extension method also create a newIServiceScope
every time?Basically, is there a meaningful difference between the following ways to create scope in both ASP.NET Core and .NET Core console apps:
public class Foo() { public Foo(IServiceProvider serviceProvider) { using(var scope = serviceProvider.CreateScope()) { scope.ServiceProvider.GetServices<>(); } } }
and
public class Bar() { public Bar(IServiceScopeFactory scopeFactory) { using(var scope = scopeFactory.CreateScope()) { scope.ServiceProvider.GetServices<>(); } } }