【问题标题】:Cannot resolve DbContext in ASP.NET Core 2.0无法在 ASP.NET Core 2.0 中解析 DbContext
【发布时间】:2017-09-05 22:01:16
【问题描述】:

首先,我正在尝试使用示例数据为我的数据库播种。我已经读到这是这样做的方法(在 Startup.Configure 中)(请参阅ASP.NET Core RC2 Seed Database

我正在使用带有默认选项的 ASP.NET Core 2.0。

像往常一样,我在ConfigureServices 中注册了我的DbContext。 但在那之后,在 Startup.Configure 方法中,当我尝试使用 GetRequiredService 解决它时,它会抛出以下消息:

System.InvalidOperationException: '无法解析范围服务 'SGDTP.Infrastructure.Context.SGDTPContext' 从根 提供者。'

我的 Startup 类是这样的:

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

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<SGDTPContext>(options => options.UseInMemoryDatabase("MyDatabase"))
        services.AddMvc();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseMvc();

        SeedDatabase(app);
    }

    private static void SeedDatabase(IApplicationBuilder app)
    {
        using (var context = app.ApplicationServices.GetRequiredService<SGDTPContext>())
        {
            // Seed the Database
            //... 
        }
    }
}

我做错了什么? 此外,这是创建种子数据的最佳场所吗?

【问题讨论】:

    标签: c# asp.net .net entity-framework asp.net-core


    【解决方案1】:

    您将SGDTPContext 注册为作用域 服务,然后尝试在作用域外部 访问它。要在 SeedDatabase 方法中创建范围,请使用以下命令:

    using (var serviceScope = app.ApplicationServices.CreateScope())
    {
        var context = serviceScope.ServiceProvider.GetService<SGDTPContext>();
    
        // Seed the database.
    }
    

    感谢 @khillang 指出 cmets 中的 CreateScope 扩展方法以及 @Tseng 的评论和 answer re 如何在 EF Core 2 中实现种子。

    【讨论】:

    • 根据我所见,似乎仍然是推荐的播种方法 嗯,不完全是。使用作用域是,但不在 Configure 方法中,按照 EF Core 2.0 在设计时发现和实例化 DbContext 的方式。有关当前推荐的方法,请参阅stackoverflow.com/a/45942026/455493。如果您继续在Configure 方法中进行播种,那么运行dotnet ef migrationsdotnet ef database update 也将执行播种,这是您在运行命令行工具时几乎不想要的
    • 仅供参考;有a CreateScope extension method directly on IServiceProvider,所以你可以删掉.GetRequiredService&lt;IServiceScopeFactory&gt;(),然后直接调用它:)
    【解决方案2】:

    在遵循官方 ASP.Net MVC Core tutorial 时遇到此错误,在您应该向应用程序添加种子数据的部分。长话短说,添加这两行

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

    SeedData 班级为我解决了这个问题:

    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.DependencyInjection;
    using System;
    using System.Linq;
    
    namespace MvcMovie.Models
    {
    public static class SeedData
    {
        public static void Initialize(IServiceProvider serviceProvider)
        {
            using (var context = new MvcMovieContext(
    
               serviceProvider.GetRequiredService<DbContextOptions<MvcMovieContext>>()))
            {
                // Look for any movies.
                if (context.Movie.Any())
                {
                    return;   // DB has been seeded
                }
      ...
    

    无法告诉您为什么,但这是我通过遵循 Alt + Enter 快速修复选项得到的两个选项。

    【讨论】:

    • 对我来说使用 serviceProvider.CreateScope().ServiceProvider.GetRequiredService>();
    【解决方案3】:
    public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
    
        public IConfiguration Configuration { get; }
    
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            var key = Encoding.ASCII.GetBytes(Configuration.GetSection("AppSettings:Token").Value);
            services.AddDbContext<DataContext>(x => x.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")).EnableSensitiveDataLogging());
            services.AddMvc();
            services.AddTransient<Seed>();
            services.AddCors();
            services.AddScoped<IAuthRepository, AuthRepository>();
            services.AddScoped<IUserRepository, UserRepository>();
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(Options =>
                {
                    Options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuerSigningKey = true,
                        IssuerSigningKey = new SymmetricSecurityKey(key),
                        ValidateIssuer = false,
                        ValidateAudience = false
                    };
                }
    
            );
    
        }
    
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env ,Seed seeder)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler(builder =>
                {
                    builder.Run(async context =>
                    {
                        context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                        context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
                        var error = context.Features.Get<IExceptionHandlerFeature>();
                        if (error != null)
                        {
                            context.Response.AddApplicationError(error.Error.Message);
                            await context.Response.WriteAsync(error.Error.Message).ConfigureAwait(false);
                        }
                    });
                });
            }
            seeder.SeedUser();
            app.UseCors(x=>x.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin().AllowCredentials());
            app.UseMvc();
        }
    }
    

    }

    【讨论】:

      猜你喜欢
      • 2018-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-03
      • 1970-01-01
      • 2020-01-05
      • 1970-01-01
      相关资源
      最近更新 更多