asp.net core - route - Tiempo de vida predeterminado del servicio de Entity Framework Core
entity framework core oracle (1)
Sí, el tiempo de vida predeterminado para DbContext
tiene un alcance. Esto es intencionado de esta manera.
La instancia de DbContext
es bastante barata y se asegura de que no uses muchos recursos. Si tiene un DbContext
con una vida útil única, todos los registros que lea una vez serán rastreados por DbContext
, a menos que deshabilite específicamente el seguimiento. Esto requerirá mucho más uso de memoria y seguirá creciendo.
Y cuanto más las pistas DbContext
, menor será el rendimiento. Es por eso que a menudo se ve que DbContext
solo se usa dentro de un bloque de using(var context = new AppDbContext())
.
Sin embargo, en las aplicaciones web, usar el bloque de using
es malo, porque el marco de trabajo administra el tiempo de vida y si lo elimina pronto, las llamadas posteriores generarán una excepción.
Si utiliza la duración transitoria en el otro lado, perderá la funcionalidad de "transacción". Con ámbito, DbContext
tiene un ámbito de transacción que es tan largo como la solicitud.
Si necesita un control más detallado, debe usar el patrón de unidad de trabajo (que DbContext
ya utiliza).
Para su segunda pregunta:
Si crea un servicio, debe tener una vida igual a la del alcance o más corta (léase: con alcance o transitorio).
Si explícitamente necesita una vida útil más larga para un servicio, debe inyectar un servicio de fábrica de DbContext
o un método de fábrica en su servicio.
Puedes lograr esto con algo como
services.AddTransient<Func<AppDbContext>>( (provider) => new Func<MyDbContext>( () => new AppDbContext()));
services.AddSingleton<IMySingletonService, MySingletonService>();
Y su servicio puede verse así:
public class MySingletonService : IMySingletonService, IDisposable
{
private readonly AppDbContext context;
public MySingletonService(Func<AppDbContext> contextFactory)
{
if(contextFactory == null)
throw new ArgumentNullException(nameof(contextFactory));
// it creates an transient factory, make sure to dispose it in `Dispose()` method.
// Since it''s member of the MySingletonService, it''s lifetime
// is effectively bound to it.
context = contextFactory();
}
}
En la aplicación ASP.NET Core puedo registrar DbContext a través de DI como este
services.AddDbContext<Models.ShellDbContext>(options => options.UseNpgsql(connection));
¿Y es interesante saber cuál es su tiempo de vida?
Desde aquí, https://github.com/aspnet/EntityFramework/blob/f33b76c0a070d08a191d67c09650f52c26e34052/src/Microsoft.EntityFrameworkCore/EntityFrameworkServiceCollectionExtensions.cs#L140 , parece que está configurado como ámbito, lo que significa que se crea una instancia de DbContext en cada solicitud.
Entonces, la primera parte de la pregunta es: ¿es verdad y, en caso afirmativo, qué tan costoso es?
Y la segunda parte es: si creo un servicio que consume DbContext, y está destinado a ser consumido por los controladores, y tendrá una API para administrar algunas entidades en DB, ¿debería registrarse también como ámbito?