65.9K
CodeProject 正在变化。 阅读更多。
Home

Mission Impossible: .NET Core 1.x 迁移到 2.0

starIconstarIconstarIconstarIconstarIcon

5.00/5 (9投票s)

2017 年 8 月 19 日

CPOL

20分钟阅读

viewsIcon

47607

.NET Core 2.0 带来了许多改进,同时也给开发人员带来了不少痛苦。我在将 .NET Core 1.x 应用程序升级到 .NET Core 2.0 时遇到了很多问题;我还没有感受到它承诺的性能提升等,但让我们看看如何升级我们现有的应用程序。

引言

每个人都在称赞 .NET Core 框架的新版本,并且都对发布关于 .NET Core、ASP.NET Core 或 Entity Framework Core 的新文章非常感兴趣。是的,我明白,但是… 关于从旧版本迁移怎么办?我个人在我将 ASP.NET Core 1.1 应用程序迁移到 ASP.NET Core 2.0 应用程序时遇到了非常大的困难。当然,系统有很多变化和改进,但如果我的应用程序无法升级以利用它们,或者它会破坏系统本身,那么这些改进就无关紧要了。我感到很恼火,所以我在想,与其写一篇关于“如何创建 ASP.NET Core 2 应用程序”的文章,我为什么不写一篇“将您现有的 ASP.NET Core 1.1 应用程序升级到 ASP.NET Core 2”的文章呢?这似乎更合理,并且是一篇符合当下需求的文章。 

图 1:Afzaal Ahmad Zeeshan 准备就位 — 顺便说一句,我的肚子没那么凸出。:D

在本文中,我将总结您可能需要更新 ASP.NET Core 1.1 应用程序的所有内容,以引入 ASP.NET Core 2 应用程序的改进。我将不关注 ASP.NET Core 本身,而是关注 .NET Core 框架,这意味着我也会讨论 Entity Framework Core 以及一些必须通过 NuGet 库进行定位的包。 

API 集发生了一些最常见的更改,我将在下面讨论,但请注意,我将专门讨论一些特定的更改。如果您的应用程序有很多更改并需要手动配置,您可能需要深入研究一下,但本文旨在解决迁移过程中 95% 的问题。 

  1. .NET Core 包升级
    1. 将包从 .NET Core 1.1 升级到 .NET Core 2。
    2. NuGet 支持
    3. 理解如何以及发生了什么变化
  2. ASP.NET Core 升级
    1. 更改身份验证系统
    2. 理解 ASP.NET Core 2 中的新元素
    3. 性能测试 — 我不会在这里做,我为此有另一篇帖子,关于负载测试。 
    4. Startup 脚本等。
  3. Entity Framework Core 调整 
    1. 理解 Entity Framework Core 2 及其变化
    2. 对系统进行更改
    3. 通过 DbContext 为数据库添加迁移
      1. 服务调用发生了一些变化,这使得它很棘手。
      2. 我将引导您完成这些更改
    4. 应用迁移,理解更改发生的位置。

我现在拥有的默认应用程序旨在演示 ASP.NET Core 身份验证系统、Entity Framework Core 技巧以及如何将 .NET Core 1.1 升级到 .NET Core 2.0 的典型更改。因此,在完成这篇文章时,您将了解控制这个快速发展过程所需的工具。 

.NET Core 升级

.NET Core 本身也可以通过命令行工具进行编程,但如果您使用 Visual Studio,项目升级会足够简单直接。但是,对于其他情况,您可能需要升级一些 csproj 文件内容,因为有一项声明指出 csproj 文件不再包含无意义的内容,而是真正地打包了项目的内容。因此,对于那些使用基于终端的环境的人来说,这可能有点棘手。或者您可能需要在那里重新配置很多东西,但是由于我将使用 Visual Studio,在这种情况下,我唯一必须更新的是属性选项卡。在此之前,我想展示 csproj 文件内容, 

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

  <PropertyGroup>
    <TargetFramework>netcoreapp1.1</TargetFramework>
    <PackageTargetFallback>$(PackageTargetFallback);portable-net45+win8+wp8+wpa81;</PackageTargetFallback>
    <UserSecretsId>aspnet-SampleAspNetCore11-A98F289E-EEAA-438F-A1D7-5C3A8E54DB2A</UserSecretsId>
  </PropertyGroup>


  <ItemGroup>
    <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.0" />
    <PackageReference Include="Microsoft.AspNetCore" Version="1.1.2" />
    <PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="1.1.2" />
    <PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="1.1.2" />
    <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="1.1.2" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.3" />
    <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.2" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.2" PrivateAssets="All" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="1.1.2" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.Design" Version="1.1.2" PrivateAssets="All" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="1.1.1" PrivateAssets="All" />
    <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="1.1.2" />
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.2" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="1.1.1" PrivateAssets="All" />
    <PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="1.1.2" />
  </ItemGroup>

  <ItemGroup>
    <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.1" />
    <DotNetCliToolReference Include="Microsoft.Extensions.SecretManager.Tools" Version="1.0.1" />
    <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="1.0.1" />
  </ItemGroup>

</Project>

在大多数情况下,您需要修改 TargetFramework 字段,并将值设置为目标 .NET Core 2.0,然后升级包版本(参见上面的包),这将为您刷新 .NET Core 目标。但是别忘了,这里有很多东西都变了,因此我建议阅读 csproj 文件参考来了解如何自己完成这项工作。 

<TargetFramework>netcoreapp2.0</TargetFramework>

在此之后,一个简单的 dotnet restoredotnet builddotnet run 就可以完成任务。总的来说,您可以执行以下命令,它将为您完成所有工作, 

$ dotnet run

包还原现在是隐式的,并且由 .NET Core 命令行工具为您完成 — 与 Visual Studio 完成的方式相同 — 然后项目会被构建并立即启动。现在,让我们将项目从 .NET Core 1.x 更新到 .NET Core 2.0 并看看有什么变化, 

图 2:在 Visual Studio 属性选项卡中更改 .NET Core 版本。

更改类型后,您会注意到(我在这里不会重复显示),现在 csproj 文件仍然指向我们旧的二进制文件,并且索引器尚未升级。但是,我们有 NuGet 包管理器来帮助我们,因此我们可以使用该工具来升级项目包。在此之前,您会看到您的 NuGet 包现在显示一个警告消息, 

图 3:更改 .NET Core 版本后,依赖项显示警告。

只需按照以下步骤操作,您的 .NET Core 就可以从 1.x 迁移到 .NET Core 2.0, 

  1. 打开 NuGet 包管理器
  2. 转到“更新”部分
  3. 选择所有包(目前我不为非 .NET Core 包提供任何支持,您可以从升级中删除它们
  4. 全部更新

这需要一些时间,因为大多数包需要被移除,其他包需要被安装,所以请耐心等待。 

图 4:在 Visual Studio 中更新 NuGet 包以将 .NET Core 从 1.x 升级到 2.0。

恭喜,此时您的应用程序将定位 .NET Core 2.0。然后您可以根据需要检查运行时信息和其他相关内容。现在,您正在定位的框架已更新,如果您只使用 .NET Core 而不是 ASP.NET Core 等其他内容,那么您的问题已经解决,因为其余的内容都与 ASP.NET Core 相关,但对于 Web 开发人员来说,问题并没有就此解决,所以各位请继续阅读下面的内容。 

ASP.NET Core 升级

现在来看一个更大的图景,ASP.NET Core 需要更多的更改,与 .NET Core 升级相比,ASP.NET Core 的 API 中有很多重大更改。有些更改是组件的重命名,然后有些更改表明某些服务已弃用并且很快将被删除,有些是微小的性能改进,但函数签名的更改会破坏构建系统。 

因此,本节将主要讨论 ASP.NET Core 2 中的更改,这些更改需要反映在 ASP.NET Core 1.1 应用程序中才能正常运行,我将把更改总结到各个部分, 

API 更改 

ASP.NET Core 框架本身发生了许多变化,应用程序管道的设计方式得到了改进,以提高性能,并且有新的方法可以构建和部署 Web 应用程序。在 ASP.NET Core 2 的公告页面上,提到了所有改进,您可以从中进行查看。让我先给您一个热身,然后我们可以继续我之前的工作。 

1. Razor 页面回来了

我明白了,Razor 一直都在,MVC 使用 Razor 等等… 但是,在这里您可以跳过控制器等。关键是,那些以前使用 Microsoft WebMatrix 工具进行开发的人,会记得 ASP.NET Web Pages 的时代,那个框架不需要 Web 应用程序的大部分复杂业务逻辑和安全抽象。现在看来,那个框架似乎又回来了。 

  1. 页面将很短,紧凑,并且只包含它们的代码。
  2. Pages 部分为此目的而定义。
  3. 页面将包含集成函数来处理 GETPOST 请求等。 

我仍然需要弄清楚这些页面,并在完成其他重要事情后写一篇关于它们的文章。 

2. Razor 页面中的 C# 7 功能支持

官方帖子中还提到,C# 7 的所有最新更新(7.1 在该官方帖子中被提及)作为一种语言也被集成到 Razor 页面中,这意味着您可以在这些页面内部使用和利用所有功能。原因在于,由于没有控制器或其他业务逻辑管理类后端,您必须在页面本身中编写代码,因此提供这些工具会更好,多亏了 Roslyn,我们拥有它。 

但是,如您所知… 这篇文章不会涵盖任何新内容,只会涵盖如何确保您的旧应用程序已升级 — 如果您确实想升级它们的话!

解决问题 

现在让我们简要看一下我们可以解决的问题。下图显示了您将面临的主要问题… 当然,在添加了这些修复和补丁后,还会有一些问题出现,因为 API 一旦集成就需要大量的进一步更改。 

图 5:应用更改到项目后,生成系统中断。

我知道您可能在想,这只需要添加一些 using 语句,但它并没有听起来那么简单。 

API 更改了很多,我很幸运我的 Web 应用程序使用的是默认值,不需要进行太多修改,这意味着我知道哪里出了问题,在哪里出了问题,因此应用更改很容易。但您做什么将完全取决于您的 Web 应用程序的进展程度。IdentityCookieOptions(在 ASP.NET Core 的外部登录中使用)已更改,现在是 IdentityConstants,它公开了 cookie 存储或登录机制和 Principals 的类型值,以及更多内容。所以,在您写了以下内容的情况下, 

public AccountController(
            UserManager<ApplicationUser> userManager,
            SignInManager<ApplicationUser> signInManager,
            IOptions<IdentityCookieOptions> identityCookieOptions,
            IEmailSender emailSender,
            ISmsSender smsSender,
            ILoggerFactory loggerFactory)
{
    _userManager = userManager;
    _signInManager = signInManager;
    _externalCookieScheme = identityCookieOptions.Value.ExternalCookieAuthenticationScheme;
    _emailSender = emailSender;
    _smsSender = smsSender;
    _logger = loggerFactory.CreateLogger<AccountController>();
}

它变成, 

public AccountController(
            UserManager<ApplicationUser> userManager,
            SignInManager<ApplicationUser> signInManager,
            IOptions<IdentityConstants> identityCookieOptions, // <-- Here
            IEmailSender emailSender,
            ISmsSender smsSender,
            ILoggerFactory loggerFactory)
{
    _userManager = userManager;
    _signInManager = signInManager;
    _externalCookieScheme = IdentityConstants.ExternalScheme;  // <-- Here
    _emailSender = emailSender;
    _smsSender = smsSender;
    _logger = loggerFactory.CreateLogger<AccountController>();
}

甚至更好的是,您可以从构造函数中移除参数,因为我们现在从 IdentityConstants 传递值。但这仅仅是因为我没有使用它,您可能出于其他目的使用了该参数,因此我没有移除它。 

Entity Framework Core API 也发生了一些更改,针对 ASP.NET Core。以前,以下内容, 

public class ApplicationUser : IdentityUser

来自 Microsoft.AspNetCore.Identity.EntityFrameworkCore,现在已更改,并且现在来自 Microsoft.AspNetCore.Identity。不仅如此,还有许多其他对象迁移到了这个命名空间,例如 IdentityRole。我认为,这是将所有内容都归入 Microsoft ASP.NET Core Identity 框架并移除 Entity Framework Core 支持该功能或服务的概念的决定,我认为这是一个好决定,因为为什么 IdentityRole 的名称会依赖于 EntityFrameworkCore 呢?所以,进行此更改可以解决问题。话虽如此,现在最终的问题是,大多数 API 要么已被弃用,要么已被改进。在这个上下文中,我无法说什么,因为我还没有对 ASP.NET Core 2 带来的性能改进量进行全面测试,但当然有主要的解决方案,甚至他们的口头解释都让您感觉到它们是框架的改进。弃用也是如此,我们可以看到团队为什么想要做出这样的改变。 

首先,让我来修复改进部分,改进部分是您的函数返回一个 type,现在它返回一个 Task<type>。 

_signInManager.GetExternalAuthenticationSchemes()...

我所做的是,我尝试查看 SignInManager 类的定义,在那里我发现定义只发生了一点小变化, 

namespace Microsoft.AspNetCore.Identity
{
    //
    // Summary:
    //     Provides the APIs for user sign in.
    //
    // Type parameters:
    //   TUser:
    //     The type encapsulating a user.
    public class SignInManager<TUser> where TUser : class
    {
        // Rest of the stuff...
        // 
        // Summary:
        //     Gets a collection of Microsoft.AspNetCore.Authentication.AuthenticationSchemes
        //     for the known external login providers.
        //
        // Returns:
        //     A collection of Microsoft.AspNetCore.Authentication.AuthenticationSchemes for
        //     the known external login providers.
        [AsyncStateMachine(typeof(SignInManager<>.<GetExternalAuthenticationSchemesAsync>d__46))]
        public virtual Task<IEnumerable<AuthenticationScheme>> GetExternalAuthenticationSchemesAsync();
        
        // Rest of the stuff...
}

因此,正如我们所知,这里发生的是我们应用 async/await 模式以异步方式获取结果,所以这里我所做的是, 

(await _signInManager.GetExternalAuthenticationSchemesAsync())...

其余代码也需要一些更改,例如 AuthenticationScheme 字段需要更改,因为它已被移除。在默认的 ASP.NET Core 代码中,ViewModel 对象本身有一个更改,它接受 IList<AuthenticationDescription> 而不是 List<AuthenticationDescription>,所以这也需要类型转换。在这些更改之后,唯一剩下的更改将是弃用。 

在大多数情况下,编译器被配置为将弃用视为错误而不是警告。因为开发人员不怕警告,但他们害怕错误… 无论它多么重大或多么微小。因此,在团队将弃用视为错误的情况下,以下方法可以解决该问题。发生的情况是,HttpContext.Authentication 即将被弃用,并在未来的更新中被移除, 

await HttpContext.Authentication.SignOutAsync(_externalCookieScheme);

这显示了警告,并且很快就会显示错误,如果未认真对待,稍后会显示生成错误。警告消息清楚地表明,您应该考虑使用提供的扩展方法来处理用户的登出过程。 

// It has been taken back from HttpContext, and instead goes to Microsoft.AspNetCore.Authentication
// HttpContext gets passed as a parameter
await Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions.SignOutAsync(HttpContext);

// Or more concisely it can be rewritten as, 
using Microsoft.AspNetCore.Authentication;

// Function call
await AuthenticationHttpContextExtensions.SignOutAsync(HttpContext);

这解决了这个问题,并且可以注释掉上一行(如果未删除)。您应该在应用程序使用登出用户的代码的每个地方考虑更新此内容,并根据身份验证进行更改。在此之后,Startup 类配置也需要一些更新,就像我们一直在观察的那样,app.UseIdentity() 也已被弃用,推荐的替代方案是 app.UseAuthentication()。其他类似的微小更改,但 API 更改和生成中断性更改已在 ASP.NET Core 2.0 中实现。 

在这个示例中,只检测到此更改,您的应用程序可能有很多更改,它们都会像这个一样。目的是让您了解可能发生的变化和中断。因此,在这些更改之后 — 并且假设我的应用程序没有其他更改,这些就是唯一需要的。现在我可以继续进行本文的最后更改,Entity Framework Core 2.0。 

Entity Framework Core 升级

在本节中,我想谈谈 Entity Framework Core 的改进,以及改进及其对其他框架的影响,例如 ASP.NET Core DbContext 对象池。我会告诉您,但我没有进行任何负载测试,所以我现在无法提供准确的指标,但很快我就会做到。 

改进

首先让我们谈谈改进,我喜欢的主要改进是能够将 DbContext 对象添加为池对象,我从 ASP.NET Core 部分跳过了它,因为该部分已经有很多内容要谈了,无论如何,这次升级说明您可以将 DbContext 添加为 DbContext 池中的对象。这样,您将获得一个存在于池中的对象,而不是每次请求到来时都重新创建对象。 

services.AddDbContext<DbContextName>(options => options.UseSqlServer(connString));

以前,您使用此来将 DbContext 注册到 DI,并且在每次请求时,ASP.NET Core 会自己创建对象,然后将其传递给您的构造函数。这很好,并且工作得非常好,但正如您可能猜到的,对于一千个请求,一千次对象实例化和 Dispose 调用,除非您配置了替代方法,例如 Singleton 或其他什么。然而,现在 ASP.NET Core 2 支持 DbContext 的池化,这意味着它创建一次对象实例并从池中重用对象,您的代码将变成, 

services.AddDbContextPool<DbContextName>(options => options.UseSqlServer(connString));

它可能为您带来的性能提升有多少,未提及,因为它取决于多种因素,因此说明任何一个因素都将是无用的。 

此外,还有一条声明关于 SQL 的 LIKE 子句可以在 Entity Framework LINQ 查询中提供和支持,现在可以实现类似这样的功能, 

var posts = from p in dbContext.Blogs.Posts
            where EF.Functions.Like(p.Name.ToLower(), "How to%"); // Lower case, pattern matching.
            select p;

但这可以通过 .NET 框架中旧的字符串管理方式来完成,例如

var posts = from p in dbContext.Blogs.Posts
            where p.Name.ToLower().StartsWith("How to"); // Lower case, pattern matching.
            select p;

旧版本在内存中执行所有这些操作,并且希望永远不会转换为 SQL LIKE 子句(我可能在这里错了),而新的 EF.Functions.Like(...) 会被翻译成 SQL LIKE 子句,并且工作是由数据库服务器完成的,而不是内存处理,这肯定会提高性能。 

问题和重大更改

总之,让我们继续讨论 Entity Framework Core 管道中的更改,我将讨论在将 ASP.NET Core 1.x 升级到 ASP.NET Core 2.0 时您将面临的问题。如果您一直在关注 GitHub 上的 .NET Core 团队,您会注意到他们在“breaking-change”标签中明确提到,API 有很多更改会中断生成系统,并且要修复它们,您需要在各个地方重新连接很多东西。例如,Entity Framework Core 存储库中当前打开的重大更改是,Issues - aspnet/EntityFrameworkCore。随时可以重新访问它们以了解更多信息,并找出在这次升级中还有哪些您正在使用但已损坏的内容。 

首先也是最重要的,需要修复的更改是,Entity Framework Core 现在需要一个默认构造函数。在一个问题中提到,Entity Framework Core 忽略构造函数中的 DbContextOptions,因为它不再遵循 DI 链,并且期望实现工厂模式,太尴尬了! 

最显著的变化是,我们将停止尝试调用 Startup.ConfigureServices()。这意味着,如果您的 DbContext 派生类型没有默认构造函数,或者不在您的 startup 或目标项目中,您将需要实现 IDbContextFactory<TContext>。

我本可以遵循新的设计并继续流程,但我的现有应用程序基于旧版本。您中的许多人会倾向于创建一个 IDbContextFactory<TContext> 类并从中实现它,但我所做的则是另一件事,我提供了一个编译时和设计时的默认构造函数实现,以便我的代码可以编译,迁移可以应用,然后我将其移除以返回到相同的 DI 服务。 

BlogContext : DbContext 的初始状态 

我没有使用示例来演示,但以下是我刚想到的上下文, 

namespace ApplicationToMigrate.Data
{
    // DbContext class
    public class BlogContext : DbContext
    {
        // DbContextOptions based constructor, for DI through
        // services.AddDbContext<BlogContext>(...);
        public BlogContext(DbContextOptions options) : base(options) { }

        public DbSet<Blog> Blogs { get; set; }
    }

    // Type declaration
    public class Blog
    {
        public string Id { get; set; }
        public string Title { get; set; }

        public List<Post> Posts { get; set; }
    }

    public class Post
    {
        public string Id { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }

        // Navigations
        public Blog Blog { get; set; }
        public string BlogId { get; set; }
    }
}

我本打算应用迁移,因为我想为 post 添加另一个字段 PublishedOn您明白这只是一个演示,对吧?),这需要一个迁移,但由于 Entity Framework Core 不调用 ConfigureServices 函数,依赖注入将不再使用,它会抱怨您必须提供一个默认构造函数。以下是那一行, 

public DateTime PublishedOn { get; set; }

现在,我搜索并发现,您可以在 官方文档页面上添加一个工厂模式,该模式返回 DbContext 的实例,我从那里捕获了以下代码, 

namespace MyProject
{
    public class BloggingContextFactory : IDesignTimeDbContextFactory<BloggingContext>
    {
        public BloggingContext Create(string[] args)
        {
            var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
            optionsBuilder.UseSqlite("Data Source=blog.db");

            return new BloggingContext(optionsBuilder.Options);
        }
    }
}

如您所见,这有效。但是,这要求在持续集成工具链的情况下,您必须跳过 DI 并开始使用此模式。如果您认为这是一种有用的方法,请坚持下去,但我并不喜欢它,所以我想要应用一个快速的技巧,让我的系统启动并运行,并确保 Entity Framework Core 也能抓住实例。所以,我做了一些更改,如下面讨论的。 

更新 BlogContext

我想要做的是,维护相同的 DI 链,并确保我的 Entity Framework Core 工作正常,我只是提供了一个默认构造函数,并通过重写 OnConfiguring 构造函数添加了相同的服务,通过 Add-MigrationUpdate-Database 命令添加迁移。以下是我的解决方案, 

namespace ApplicationToMigrate.Data
{
    public class BlogContext : DbContext
    {
        public BlogContext(DbContextOptions options) : base(options) { }
        public BlogContext() { } // Default constructor

        // Needed by EF tools
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=aspnet-ApplicationToMigrate-3C3829CB-5A83-4BD3-8141-288E09E3FF88;Trusted_Connection=True;MultipleActiveResultSets=true");
        }

        public DbSet<Blog> Blogs { get; set; }
    }

    // Types are similar, as shown above.
}

在您开始攻击我之前,我想说明您不需要在这里添加这段代码,如果您使用版本控制,这段代码可以移除而不破坏任何东西,因为它不是应用程序必需的。让我列出几点,您中的大多数人可能不明白这一点而开始攻击, 

  1. 默认构造函数和重写函数不是 ASP.NET Core 2.0 所必需的。 
  2. 一旦应用了迁移,就可以移除它们。 
    1. 您的连接字符串也是如此,代码中不需要它们。 
    2. 您仍然可以按照 appsettings.json 的方式存储设置,或考虑其他轻松存储连接字符串的方法(例如 Microsoft Azure App Service 的默认值,用于连接字符串等),因为在运行时是您的 Startup 类维护一切。 
  3. 问题只是 Entity Framework Core 无法从 Startup 类捕获此实例,仅在 ASP.NET Core 1.x 中
  4. 在 ASP.NET Core 2.0 中,您仍然可以使用相同的代码,并且不需要提供默认构造函数,因为 Entity Framework Core 团队更新了他们的工具链,并管理着管道中服务的创建方式,并按需执行。 

这让我们回到这个说法,在大多数情况下,您应该考虑也将函数管道迁移到 ASP.NET Core 2.0,尽管如此,如果您非常依赖 ASP.NET Core 1.x,那么您的希望就很渺茫了,希望 .NET Core 团队很快会发布一个脚本来升级 .NET Core 1.x 应用到 .NET Core 2 应用程序,逐级向下迁移到 ASP.NET Core 和 Entity Framework Core,为用户提供美好的体验。 

最后的寄语

我在本文中分享了我找到的升级建议,希望如果您想应用这些更改,这篇文章会有所帮助。我将继续关注与 .NET Core 迁移相关的其他问题和疑难,我会在那里分享。如果您发现我遗漏了一些地方,请告诉我,我告诉您的更改是个人意见,它们可能不是最佳方法 — 例如 DbContext 中的默认构造函数问题。 

如果您的应用程序仍然无法正常工作或无法生成,请按照以下步骤操作, 

  1. 尝试在 Google 上搜索问题,很可能您会在 GitHub 上找到讨论帖。 
  2. 应用那些更改,看看会发生什么。 
  3. 在这里评论,我会尝试找到解决方案并在此发布。 
  4. 如果一切都不奏效,您可能需要创建一个新的 ASP.NET Core 2.0 模板项目,然后手动迁移所有内容,除非他们发布一个迁移脚本。 

请原谅我一会儿,我很快就会提供一个单独的基于测试的替代方案,它将讨论您从这些更改中获得的改进程度。ASP.NET Core 负载测试、Entity Framework Core SQL 剖析器等等都可以涵盖,但在本文中,我的重点是确保您能够尽快知道如何解决这些常见问题。我理解这一点,因为我自己也经历过。 

© . All rights reserved.