Incapaz de resolver el servicio para el tipo 'Microsoft.EntityFrameworkCore.DbContextOptions '

Estoy tratando de acceder al databse usando EF Core 5.0 en un ASP. Proyecto NET Core. Para la primera migración, yo superé la OnConfiguring() método en el DBContext y actualizado la base de datos con éxito.

Para la segunda migración, decidí usar la inyección de dependencia en ASP. NET Core following the Directrices. Aquí están los cambios que hice.

  1. Añadido services.AddDbContext en mi Startup.cs.
  2. Retirada OnConfiguring() método de DBContext.

Después de correr dotnet ef migrations add Posts, obtengo el siguiente error:

Microsoft.EntityFrameworkCore.Design.OperationException: 
Unable to create an object of type 'BlogContext'. 
For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728

Si agrego la bandera --verbose, obtengo esta salida:

Build started...
dotnet build blog/app/app.csproj /verbosity:quiet /nologo

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:02.50
Build succeeded.

Finding DbContext classes...
Finding IDesignTimeDbContextFactory implementations...
Finding application service provider in assembly 'app'...
Finding Microsoft.Extensions.Hosting service provider...
No static method 'CreateHostBuilder(string[])' was found on class 'Program'.
No application service provider was found.
Finding DbContext classes in the project...
Found DbContext 'BlogContext'.
Microsoft.EntityFrameworkCore.Design.OperationException: Unable to create an object of type 'BlogContext'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
 ---> System.InvalidOperationException: Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContextOptions`1[app.Data.BlogContext]' while attempting to activate 'app.Data.BlogContext'.
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters)
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetServiceOrCreateInstance(IServiceProvider provider, Type type)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.<>c__DisplayClass13_4.b__13()
   
Unable to create an object of type 'BlogContext'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
 

Sin embargo, el código funciona como se esperaba cuando ejecuto la aplicación web, como en el BlogContext es creado e inyectado en mis clases por la capa DI, y puedo acceder a la base de datos.

Por lo tanto, estoy adivinando que la capa DI no funciona como se espera cuando se ejecuta la dotnet ef migrations add Comando.

Aquí está mi código.

// Program.cs

public class Program
{
    public static void Main(string[] args)
    {
        IHostBuilder builder = Host.CreateDefaultBuilder(args)
                                        .UseSerilog()
                                        .ConfigureWebHostDefaults(webBuilder =>
                                        {
                                            webBuilder.UseStartup();
                                        });

        IHost host = builder.Build();

        host.Run();
    }
}

// BlogContext

using app.Models;
using Microsoft.EntityFrameworkCore;

namespace app.Data
{
    public class BlogContext : DbContext
    {
        public DbSet Posts { get; set; }

        public DbSet Comments { get; set; }

        public BlogContext(DbContextOptions options) : base(options)
        {

        }
    }
}

// Startup.cs

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;

public class Startup
{
    public Startup(IConfiguration configuration)
    {
         Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public string ConnectionString => Configuration.GetConnectionString("Blog");

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext(opt => { opt.UseSqlite(ConnectionString); });
    }
}

Ambos Startup y BlogContext vivir en el mismo proyecto.

Pregunta hecha hace 3 años, 5 meses, 0 días - Por htmlhero


4 Respuestas:

  • En mi experiencia, mejor crear una clase (en el mismo proyecto que el contexto) que implementa IDesignTimeDbContextFactory - como se describe Aquí.. De esa manera, no se adivina qué código se utilizará al utilizar las herramientas de tiempo de diseño como la actualización-database

    Respondida el Dec 17, 2020 a las 09:12 - por compilercaptain7dab

    Votos positivos: 0 | Votos negativos: 0

  • Gracias a los comentarios de Ivan y Kirk arriba y leyendo toda la salida del verbose, descubrí el problema. Resulta que no estaba siguiendo el patrón correcto Program.cs.

    Desde documentación,

    The tools first try to obtain the service provider by invoking Program.CreateHostBuilder(), calling Build(), then accessing the Services property.

    Había refactorizado el original Program.cs moviéndose CreateHostBuilder() dentro main(), que rompió la migración ef-core.

    Después de modificar el Program.cs para seguirlo funciona como se espera.

    public class Program
    {
        public static void Main(string[] args)
            => CreateHostBuilder(args).Build().Run();
    
        // EF Core uses this method at design time to access the DbContext
        public static IHostBuilder CreateHostBuilder(string[] args)
            => Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(
                    webBuilder => webBuilder.UseStartup());
    }
    

    Respondida el Dec 17, 2020 a las 09:20 - por coderconqueror

    Votos positivos: 0 | Votos negativos: 0

  • El error que estás experimentando se produce porque Entity Framework Core no puede resolver el DbContextOptions necesario para crear una instancia de tu BlogContext al ejecutar el comando dotnet ef migrations add.

    Para solucionar este problema, puedes agregar una implementación de IDesignTimeDbContextFactory para BlogContext en tu proyecto. Esto le proporcionará a Entity Framework Core una forma de crear una instancia del DbContext sin depender de la inyección de dependencias del contenedor de servicios de ASP.NET Core.

    Aquí está cómo puedes hacerlo:

    • Crea una clase que implemente la interfaz IDesignTimeDbContextFactory en tu proyecto:
    csharp
    using Microsoft.EntityFrameworkCore;
    using Microsoft.EntityFrameworkCore.Design;
    using Microsoft.Extensions.Configuration;
    
    namespace app.Data
    {
        public class BlogContextFactory : IDesignTimeDbContextFactory
        {
            public BlogContext CreateDbContext(string[] args)
            {
                var optionsBuilder = new DbContextOptionsBuilder();
                optionsBuilder.UseSqlite("your_connection_string_here");
    
                return new BlogContext(optionsBuilder.Options);
            }
        }
    }
    
    • Reemplaza `"your_connection_string_here"` con tu cadena de conexión real en el método CreateDbContext de la clase BlogContextFactory.
    • Ahora, cuando ejecutes el comando `dotnet ef migrations add`, Entity Framework Core podrá usar la implementación de IDesignTimeDbContextFactory para crear una instancia de BlogContext sin depender de la inyección de dependencias.

    Con esta implementación, el error que estás experimentando al ejecutar los comandos de migración debería resolverse y podrás continuar trabajando con tus migraciones de base de datos de manera efectiva.

    Respondida el Dec 18, 2020 a las 09:12 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • El error indica que el servicio Microsoft.EntityFrameworkCore.DbContextOptions con el tipo genérico BlogContext no se puede resolver cuando se ejecuta el comando dotnet ef migrations add. Esto sugiere que la configuración de inyección de dependencia en Startup.cs no está configurada correctamente.

    He aquí algunos pasos que puedes seguir para solucionar el problema:

    • Verifica la cadena de conexión: Asegúrate de que la cadena de conexión definida en `ConnectionString` sea válida y apunte a la base de datos correcta.
    • Registra el contexto de DB correctamente: En `ConfigureServices`, asegúrate de registrar el contexto de DB utilizando el tipo genérico correcto:

    
       services.AddDbContext();
       

    • Crea un constructor sin parámetros para el contexto de DB: El constructor del contexto de DB debe tener un constructor sin parámetros para que la inyección de dependencia funcione correctamente.

    
       public BlogContext()
       {

    }

    • Usa el constructor sin parámetros en `Startup.cs`: En `ConfigureServices`, utiliza el constructor sin parámetros al registrar el contexto de DB:

    
       services.AddDbContext(options => options.UseSqlite(ConnectionString));
       

    • Añade el paquete NuGet "Microsoft.EntityFrameworkCore.Sqlite": Asegúrate de que el paquete NuGet "Microsoft.EntityFrameworkCore.Sqlite" esté instalado en el proyecto que contiene el contexto de DB. Este paquete proporciona el proveedor de SQLite para EF Core.

    Si seguiste estos pasos y el problema persiste, proporciona el código completo de Program.cs, Startup.cs y BlogContext.cs para una revisión más detallada.

    Respondida el Dec 18, 2020 a las 09:23 - por Gemini

    Votos positivos: 0 | Votos negativos: 0