首次迁移时访问 Microsoft.Extensions.Hosting 服务时出错

Posted

技术标签:

【中文标题】首次迁移时访问 Microsoft.Extensions.Hosting 服务时出错【英文标题】:An error occurred while accessing the Microsoft.Extensions.Hosting services when do first migrations 【发布时间】:2020-06-19 01:24:08 【问题描述】:

我不明白哪里错了。 我试图用一个非常简单的模型在.net core mvc中制作一个简单的crud,它的字段很少。

这些是我的模型:

    public class Employee
    
        [Key] public int EmployeeId  get; set; 

        [Required] public string FistName  get; set; 

        [Required] public string LastName  get; set; 

        public int PositionId  get; set; 
        public virtual Position Position  get; set; 

    
public class Position
    
        [Key]
        public int PositionId  get; set; 
        public string PositionName  get; set; 
        public ICollection<Employee> Employees  get; set; 
    

然后我创建了应用上下文:

public class EmployeeContext : DbContext

    public EmployeeContext(DbContextOptions<EmployeeContext> options)
        : base(options)
    
    

    public DbSet<Employee> Employees  get; set; 
    public DbSet<Position> Positions  get; set; 

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    
        modelBuilder.Entity<Employee>()
            .HasOne(e => e.Position)
            .WithMany()
            .HasForeignKey(e => e.PositionId);
    

并在 Startup.cs 中注册上下文:

 public void ConfigureServices(IServiceCollection services)
    
        services.Configure<CookiePolicyOptions>(options =>
        
            // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        );

        services.AddDbContext<EmployeeContext>(item =>item.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);                
        

可能还需要一个.csproj和program.cs的文件代码

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net461</TargetFramework>
    <DebugType>full</DebugType>
  </PropertyGroup>


  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.CookiePolicy" Version="2.2.8" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.2" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.2">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.2" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.Design" Version="1.1.6" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.2">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.Extensions.Logging.Configuration" Version="3.1.2" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.1" />
  </ItemGroup>

</Project>

public class Program
    
        public static void Main(string[] args)
        
            CreateWebHostBuilder(args).Build().Run();
        

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();
    

然后我尝试先迁移,但我看到一个非常奇怪的错误 Add-Migration FirstInit -verbose

Using project 'Crud'.
Using startup project 'Crud'.
Build started...
Build succeeded.
C:\.nuget\packages\microsoft.entityframeworkcore.tools\3.1.2\tools\net461\win-x86\ef.exe migrations add FirstInit --json --verbose --no-color --prefix-output --assembly C:\source\repos\Crud\Crud\bin\Debug\net461\Crud.exe --startup-assembly C:\source\repos\Crud\Crud\bin\Debug\net461\Crud.exe --project-dir C:\source\repos\Crud\Crud\ --language C# --working-dir C:\source\repos\Crud --root-namespace Crud
Using assembly 'Crud'.
Using startup assembly 'Crud'.
Using application base 'C:\source\repos\Crud\Crud\bin\Debug\net461'.
Using working directory 'C:\source\repos\Crud\Crud'.
Using root namespace 'Crud'.
Using project directory 'C:\source\repos\Crud\Crud\'.
Using configuration file 'C:\source\repos\Crud\Crud\bin\Debug\net461\Crud.exe.config'.
Using assembly 'Crud'.
Using startup assembly 'Crud'.
Using application base 'C:\source\repos\Crud\Crud\bin\Debug\net461'.
Using working directory 'C:\source\repos\Crud\Crud'.
Using root namespace 'Crud'.
Using project directory 'C:\source\repos\Crud\Crud\'.
Finding DbContext classes...
Finding IDesignTimeDbContextFactory implementations...
Finding application service provider...
Finding Microsoft.Extensions.Hosting service provider...
Using environment 'Development'.
System.TypeLoadException: There is no implementation of the GetItem method in the type "Microsoft.AspNetCore.Mvc.Razor.Internal.FileProviderRazorProjectFileSystem" from assembly "Microsoft.AspNetCore.Mvc.Razor, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60".
   в Microsoft.Extensions.DependencyInjection.MvcRazorMvcCoreBuilderExtensions.AddRazorViewEngineServices(IServiceCollection services)
   в Microsoft.Extensions.DependencyInjection.MvcRazorMvcCoreBuilderExtensions.AddRazorViewEngine(IMvcCoreBuilder builder)
   в Microsoft.Extensions.DependencyInjection.MvcServiceCollectionExtensions.AddMvc(IServiceCollection services)
   в Crud.Startup.ConfigureServices(IServiceCollection services) в C:\source\repos\Crud\Crud\Startup.cs:строка 38
--- End the stack trace from the previous location where the exception occurred ---
   в System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   в Microsoft.AspNetCore.Hosting.ConventionBasedStartup.ConfigureServices(IServiceCollection services)
   в Microsoft.AspNetCore.Hosting.Internal.WebHost.EnsureApplicationServices()
   в Microsoft.AspNetCore.Hosting.Internal.WebHost.Initialize()
   в Microsoft.AspNetCore.Hosting.WebHostBuilder.Build()
An error occurred while accessing the Microsoft.Extensions.Hosting services. Continuing without the application service provider. Error: There is no implementation of the GetItem method in the type "Microsoft.AspNetCore.Mvc.Razor.Internal.FileProviderRazorProjectFileSystem" from assembly "Microsoft.AspNetCore.Mvc.Razor, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60".
No application service provider was found.
Finding DbContext classes in the project...
Found DbContext 'EmployeeContext'.
Microsoft.EntityFrameworkCore.Design.OperationException: Unable to create an object of type 'EmployeeContext'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728 ---> System.MissingMethodException:There are no parameterless constructors defined for this object..
   в System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
   в System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   в System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   в System.Activator.CreateInstance(Type type, Boolean nonPublic)
   в System.Activator.CreateInstance(Type type)
   в Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.<>c__DisplayClass13_3.<FindContextTypes>b__13()
   --- End trace of internal exception stack ---
   в Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.<>c__DisplayClass13_3.<FindContextTypes>b__13()
   в Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func`1 factory)
   в Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
   в Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType)
   в Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType)
   в Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()
   в Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   в Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Unable to create an object of type 'EmployeeContext'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728

这 3 行有什么问题?

【问题讨论】:

你安装了Microsoft.EntityFrameworkCore.Design吗? 我安装了 Microsoft.EntityFrameworkCore.Design,我看到了同样的错误 您能分享有关 Program.cs 文件的详细信息吗? 添加问题 一切看起来都不错,你能添加-Migration FirstInit -verbose 看看你能不能得到更多细节? 【参考方案1】:

EF 调用 CreateWebHostBuilder 或 BuildWebHost 而不运行 Main。所以 Iconfiguration 为空。

创建继承自 IDesignTimeDbContextFactory 的新类。

public class YourDbContext : DbContext

//Dbcontext implementation


public class YourDbContextFactory : IDesignTimeDbContextFactory<YourDbContext>

    public YourDbContext CreateDbContext(string[] args)
    
        var optionsBuilder = new DbContextOptionsBuilder<YourDbContext>();
        optionsBuilder.UseSqlServer("your connection string");

        return new YourDbContext(optionsBuilder.Options);
    

您正在使用一个使用 IHostBuilder 的新 .net 核心 EF。(在像您这样的旧版本中,提供程序是 IWebHostBuilder)。这些工具首先尝试通过调用 Program.CreateHostBuilder()、调用 Build() 来获取服务提供者,然后访问 Services 属性。 您可以从Here 了解更多关于设计时 DbContext 创建的信息

它可能发生在您的启动文件中的某个条件或您正在注入时。例如,您有一个标志来检查 appsetting 中的某个变量是否为真以使用内存数据库实例。

EF 需要在不启动应用程序的情况下构建模型并使用 DbContext。当 EF 调用方法时,您的配置服务仍然为 null,这就是您收到错误的原因。

确保您已安装软件包

Microsoft.EntityFrameworkCore.Tools

【讨论】:

很好用!有没有办法使用 args 传递连接字符串而不是硬编码? @Cladoo 检查此链接gist.github.com/tonysneed/… 另外值得一提的是,在某些情况下,如果在 Startup.cs 的 ConfigureServices 中有一些 DI 类没有注册,可能会出现这样的错误。这就是我的场景。【参考方案2】:

正如accepted 答案所建议的那样:

EF 调用 CreateWebHostBuilder 或 BuildWebHost 而不运行 Main。所以 我的配置为空。

但您可以通过覆盖OnConfiguring来使用这个简单的解决方案,而不是使用更复杂的工厂。

public class ApplicationDbContext : DbContext
        
    public ApplicationDbContext() 
        
    
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
                
    

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    
        if (!optionsBuilder.IsConfigured)
        
            optionsBuilder.UseSqlServer("Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=Chinook");
        
    

*注意不要在源码(docs)中使用db连接字符串

dotnet user-secrets set ConnectionStrings:Chinook "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Chinook"
dotnet ef dbcontext scaffold Name=ConnectionStrings:Chinook Microsoft.EntityFrameworkCore.SqlServer

还要注意在cli命令行中只使用一个\。

【讨论】:

【参考方案3】:

就我而言,我删除了括号之间的参数:

之前:

services.AddDbContext<EmployeeContext>(item =>item.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

之后:

services.AddDbContext<EmployeeContext>();

关注Docs

【讨论】:

以上是关于首次迁移时访问 Microsoft.Extensions.Hosting 服务时出错的主要内容,如果未能解决你的问题,请参考以下文章

自定义捆绑迁移在首次安装时失败,因为它们在 OroCommerce 的安装程序之前运行

实体框架代码首次迁移文件源代码控制

启用 EF 代码首次迁移后 Azure 网站出现内部服务器错误

如何禁用代码首次迁移

创建的Sdf在代码首次迁移后被删除

风格迁移(Style Transfer)首次学习总结