.NET Core IServiceScopeFactory.CreateScope() vs IServiceProvider.CreateScope() extension
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
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
.