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





5.00/5 (9投票s)
.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”的文章呢?这似乎更合理,并且是一篇符合当下需求的文章。
在本文中,我将总结您可能需要更新 ASP.NET Core 1.1 应用程序的所有内容,以引入 ASP.NET Core 2 应用程序的改进。我将不关注 ASP.NET Core 本身,而是关注 .NET Core 框架,这意味着我也会讨论 Entity Framework Core 以及一些必须通过 NuGet 库进行定位的包。
API 集发生了一些最常见的更改,我将在下面讨论,但请注意,我将专门讨论一些特定的更改。如果您的应用程序有很多更改并需要手动配置,您可能需要深入研究一下,但本文旨在解决迁移过程中 95% 的问题。
- .NET Core 包升级
- 将包从 .NET Core 1.1 升级到 .NET Core 2。
- NuGet 支持
- 理解如何以及发生了什么变化
- ASP.NET Core 升级
- 更改身份验证系统
- 理解 ASP.NET Core 2 中的新元素
- 性能测试 — 我不会在这里做,我为此有另一篇帖子,关于负载测试。
- Startup 脚本等。
- Entity Framework Core 调整
- 理解 Entity Framework Core 2 及其变化
- 对系统进行更改
- 通过
DbContext
为数据库添加迁移- 服务调用发生了一些变化,这使得它很棘手。
- 我将引导您完成这些更改
- 应用迁移,理解更改发生的位置。
我现在拥有的默认应用程序旨在演示 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 restore
或 dotnet build
或 dotnet run
就可以完成任务。总的来说,您可以执行以下命令,它将为您完成所有工作,
$ dotnet run
包还原现在是隐式的,并且由 .NET Core 命令行工具为您完成 — 与 Visual Studio 完成的方式相同 — 然后项目会被构建并立即启动。现在,让我们将项目从 .NET Core 1.x 更新到 .NET Core 2.0 并看看有什么变化,
更改类型后,您会注意到(我在这里不会重复显示),现在 csproj 文件仍然指向我们旧的二进制文件,并且索引器尚未升级。但是,我们有 NuGet 包管理器来帮助我们,因此我们可以使用该工具来升级项目包。在此之前,您会看到您的 NuGet 包现在显示一个警告消息,
只需按照以下步骤操作,您的 .NET Core 就可以从 1.x 迁移到 .NET Core 2.0,
- 打开 NuGet 包管理器
- 转到“更新”部分
- 选择所有包(目前我不为非 .NET Core 包提供任何支持,您可以从升级中删除它们)
- 全部更新
这需要一些时间,因为大多数包需要被移除,其他包需要被安装,所以请耐心等待。
恭喜,此时您的应用程序将定位 .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 应用程序的大部分复杂业务逻辑和安全抽象。现在看来,那个框架似乎又回来了。
- 页面将很短,紧凑,并且只包含它们的代码。
- Pages 部分为此目的而定义。
- 页面将包含集成函数来处理
GET
和POST
请求等。
我仍然需要弄清楚这些页面,并在完成其他重要事情后写一篇关于它们的文章。
2. Razor 页面中的 C# 7 功能支持
官方帖子中还提到,C# 7 的所有最新更新(7.1 在该官方帖子中被提及)作为一种语言也被集成到 Razor 页面中,这意味着您可以在这些页面内部使用和利用所有功能。原因在于,由于没有控制器或其他业务逻辑管理类后端,您必须在页面本身中编写代码,因此提供这些工具会更好,多亏了 Roslyn,我们拥有它。
但是,如您所知… 这篇文章不会涵盖任何新内容,只会涵盖如何确保您的旧应用程序已升级 — 如果您确实想升级它们的话!
解决问题
现在让我们简要看一下我们可以解决的问题。下图显示了您将面临的主要问题… 当然,在添加了这些修复和补丁后,还会有一些问题出现,因为 API 一旦集成就需要大量的进一步更改。
我知道您可能在想,这只需要添加一些 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-Migration
和 Update-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.
}
在您开始攻击我之前,我想说明您不需要在这里添加这段代码,如果您使用版本控制,这段代码可以移除而不破坏任何东西,因为它不是应用程序必需的。让我列出几点,您中的大多数人可能不明白这一点而开始攻击,
- 默认构造函数和重写函数不是 ASP.NET Core 2.0 所必需的。
- 一旦应用了迁移,就可以移除它们。
- 您的连接字符串也是如此,代码中不需要它们。
- 您仍然可以按照
appsettings.json
的方式存储设置,或考虑其他轻松存储连接字符串的方法(例如 Microsoft Azure App Service 的默认值,用于连接字符串等),因为在运行时是您的Startup
类维护一切。
- 问题只是 Entity Framework Core 无法从
Startup
类捕获此实例,仅在 ASP.NET Core 1.x 中。 - 在 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
中的默认构造函数问题。
如果您的应用程序仍然无法正常工作或无法生成,请按照以下步骤操作,
- 尝试在 Google 上搜索问题,很可能您会在 GitHub 上找到讨论帖。
- 应用那些更改,看看会发生什么。
- 在这里评论,我会尝试找到解决方案并在此发布。
- 如果一切都不奏效,您可能需要创建一个新的 ASP.NET Core 2.0 模板项目,然后手动迁移所有内容,除非他们发布一个迁移脚本。
请原谅我一会儿,我很快就会提供一个单独的基于测试的替代方案,它将讨论您从这些更改中获得的改进程度。ASP.NET Core 负载测试、Entity Framework Core SQL 剖析器等等都可以涵盖,但在本文中,我的重点是确保您能够尽快知道如何解决这些常见问题。我理解这一点,因为我自己也经历过。