EKsumic's Blog

let today = new Beginning();

Click the left button to use the catalog.

OR

.NET Core 2.1 迁移至 3.1 踩坑记录

.NET Core 2.1 迁移至 3.1 踩坑记录

首先,第一个大坑也是迁移到3.1到最后已经No Error才发现的:

你再也不能使用SQL Server 2008 R2了!

你再也不能使用SQL Server 2008 R2了!

你再也不能使用SQL Server 2008 R2了!

.NET Core LTS

这个2012 R2+可不是写着玩的,是真的必须升级数据库!

 

好,接着讲其它的坑:

HRESULT:0x80020009

当你把Visual Studio 2019升级到16.6.2的时候,你的nuget包管理器就装不上任何包了,会一直报错,

Exception from HRESULT: 0x80020009 (DISP_E_EXCEPTION)

至少在我的项目里面是这样的。

其实,我也不是第一个遇到这个问题的,这个问题早在5月1号就提出过,到今天6月20号社区给出的一个解决方案是回退版本。

实际上,这个修复影响并不大,因为用Powershell照样可以安装包的。只是IDE上的nuget管理器用不起来了而已。

例如:

Install-Package Microsoft.AspNetCore.Identity.UI

Install-Package Microsoft.AspNetCore.Identity.UI

 

如何从2.1向3.1迁移:

1.修改目标框架

<!--<TargetFramework>netcoreapp2.1</TargetFramework>-->

<TargetFramework>netcoreapp3.1</TargetFramework>

并去除

<PackageReference Include="Microsoft.AspNetCore.App" />

2. 升级依赖的NuGet包

update-package <package_name>

3.startup.cs文件

IHostingEnvironment 已过时, 要修改为IWebHostEnvironment

去除app.UseDatabaseErrorPage();

//app.UseMvc(routes =>
//{
//    routes.MapRoute(
//        name: "default",
//        template: "{controller=MainPage}/{action=Index}/{id?}");
//});

改成:

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name:"default",
        pattern: "{controller=MainPage}/{action=Index}/{id?}"
        );
});

……

其它的按照ERROR提示,一步一步nuget包装好,装对,基本没有太大问题。

 

 

最后,回顾一下大坑

b => b.UseRowNumberForPaging()

如果你尝试在上下文DBContext的连接SQL Server的字符串后面写这个,就一定会有绿线标记。

这个方法,并没有完全被标记为弃置,但已经没任何用了。

这个方法是用来照顾SQL Server 2008的使用者的,但是.NET Core 3.0版本之后,表示不再支持UseRowNumberForPaging()

UseRowNumberForPaging()

你不能在前台的Razor页面里面用Take()或者Skip()方法,因为在旧版数据库中,这意味着使用关键字FETCH NEXT……

要么继续呆在.NET Core 2.1,要么升级数据库。

微软官方的意思是不再维护这个方法了,甚至不打算出替代方案。

 

我选择了升级数据库:

  1. 检查版本号,我的版本号是10.50.4000.0,是SP2版本。

SQL Server Version 2008 r2 10.50.4000.0

  1. 查看官方文档提供的升级路径

Microsoft SQL Server upgrade Manual

  1. 得知我的SP2版本要先升级到SP3,再升级到Express
  2. 10.50.4000.0->10.50.6000.34 Microsoft® SQL Server® 2008 R2 的 Service Pack 3
  3. 最后用SQL Server 2016的完整安装包安装
  4. 注意你下载到的将会是2016 SP2的下载器,选择Advanced下载完整文件。

然后升级完成之后,会发现UI没换:

MMSM

但点开属性,可以发现版本以为13.0,原版本是10.50.4000.0。

Microsoft Sql Sever version cat

 

别着急,尽管这样,还会报错:

There is already an open DataReader associated with this Command which must be closed first.

这个是3.1的特性,为了提高安全性,防止内存泄漏,防止注入……

直接的解决方案是在连接字符串后面增加MultipleActiveResultSets=true;

其实在写代码的阶段的时候尽量就应该注意避免打开多个DataReader,但是因为我的是个人博客,不太需要在乎这些事情。

接着是用数据字典+LINQ产生的Error:

InvalidOperationException: The LINQ expression could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

你惊讶的发现,你的Linq语句没有被translated,虽然检测语法通过,但最终还是抛出了异常。

这个是.NET Core 3.0版本之后,通过评估性能,而拒绝掉的一些linq特性,因为这样的Linq可能会造成服务器性能下降。

如果你用了GroupBy那就得更加注意了,这是详细的解决方案:

The LINQ expression could not be translated. Eiither rewrite the query in a form that can be translated --StackOverflow

我的理解是,不要GroupBy,想办法换成其它的。所以我尝试在GroupBy之前加了AsEnumerable()。(但实际上你得重构代码)

 

接着又报另一个错误:

OFFSET”附近有语法错误。 在 FETCH 语句中选项 NEXT 的用法无效

这个主要是在sql server 2008中,不支持FETCH和NEXT语句(sql server 2012才支持)(但是我已经换到2016了啊)

原因猜测:

SQL Sever 2016 Express SP2并没有成功安装。

尽管从PowerShell里面看到SQL Server的Vesion已经升级到13.x,但是在执行语句的标准上,看起来好像还是按照2008R2的来的。

于是我直接卸载了SQL Server 2008 R2 Express和SQL Server 2016 SP2 Express,直接重新安装SQL Server 2017 Express。(完全卸载SQL Server和安装SQL Server折腾了不少时间)

最后,总算是解决了FETCH NEXT语句的问题。总的来说,数据库安装真的是费了不少精力,我一度甚至想重装系统,后来想到,去拿阿里云服务器测试,装坏了就重开镜像,方便了很多,终于是试完了解决了问题。

 

附录:

https://docs.microsoft.com/zh-cn/aspnet/core/migration/30-to-31

https://docs.microsoft.com/zh-cn/aspnet/core/migration/22-to-30

https://docs.microsoft.com/zh-cn/aspnet/core/migration/21-to-22

SQL Server相关:

[1] 彻底卸载SQL Server

[2] SqlServer 2008R2 10.50.1600.1 升级到 SqlServer 2016

Exception from HRESULT: 0x80020009相关:

[1] Introduce the ability to roll back a Visual Studio Update

[2] Exception occurred. (Exception from HRESULT: 0x80020009 (DISP_E_EXCEPTION))

[3] Exception occurred. (Exception from HRESULT: 0x80020009 (DISP_E_EXCEPTION)) #6177

This article was last edited at 2020-06-21 15:23:43

* *