浏览器报错页面:
SqlException: 关键字 'SELECT' 附近有语法错误。 “)”附近有语法错误。 “OFFSET”附近有语法错误。 在 FETCH 语句中选项 NEXT 的用法无效。
错误位置:
这是一个来自.NET Core 2.1 迁移到3.1之后发生的错误,开始我是以为是数据库问题,升级了数据库之后,依旧报错。于是我选择了卸载所有数据库并重新安装SQL Server 2017 Express版本,然后报错依旧……
我认为代码是没有错误的,因为它在.NET Core 2.1正常运行了。(也就是我现在正在用的博客项目)
我加过断点调试,只有当return的一瞬间会跑到WEB页面报错,原因应该是前台Razor页面获取不到BlogsModel,于是我尝试直接传递BlogsModel给前台,最终在foreach语句停下,仍然报的是一样的错误……
我怀疑是数据库没装好,于是尝试直接在数据库里面用FETCH NEXT语句执行查询,发现执行成功!暂时排除了数据库问题。
那么问题应该出在ORM上面了,EntityFramework在把我的语句翻译成SQL的时候发生了致命的错误,这个问题应该不在我身上。
因为不是特别懂FETCH NEXT语句,所以姑且认为是ORM的问题,或者直接说是.NET Core 3.1 的问题,因为3.1废除了UseRowNumberForPaging()这个方法,同时还严格限制GroupBy语句的使用,使我不得不在GroupBy之前增加AsEnumerable()。
3.1相对2.1有很大的性能提升,如果说是通过严格限制LINQ语句来达成的话,那我觉得我还不如直接写SQL吧。
对于该错误,我还存在疑惑:
- 我是否真的安装成功了SQL Server?
- 是否真的是3.1的EntityframeworkCore的问题,BUG?
- 是否因为早期版本的原因,Visual Studio 2019 Community默认还是以2008 R2的引擎在驱动?
第一个困惑 来源于全文和语义提取搜索,因为没有用过,并且也搜索不到是否与FETCH NEXT有关,猜测可能是因为没装这个功能所引起的。(但后来发现,这个功能根本装不上去,所以就想到去拿阿里云的云服务器去试,最后发现阿里云有两层防火墙,根本进不来1433端口,所以就此罢休)
在自己的开发环境,2008R2和2017的实例共存的情况下,在2017里建立存储过程中用到了FETCH NEXT发现可以执行,所以姑且先排除了全文和语义提取搜索这个可能。我觉得根本原因还是EntityFrameworkCore没有把我的LINQ语句正确转换成SQL,这是直接原因。
间接原因我想有2点:
- 错误的迁移方式,后台并不认为前台是Razor
- .NET Core 3.1 固有Bug
我倾向于第2点,因为第一点我已经重新写过一个3.1项目,试过了依然报错。
.NET Core 3.1 是LTS版本,意味着会去维护和修复,这个版本还很不完整,所以这种BUG可能存在,而且还是只有我碰到了,因为我的代码逻辑不倾向于性能。逻辑上实现了,但是可能多次重复查询字段,最好的方式当然是读1次数据库然后开始处理,我大概为了去对比某些字段而读取了好几次……但这些都不是重点,关键是.NET Core 3.1限制了GroupBy的使用,这意味着我可能要用两个Where去替代它,要产生更多的代码量。
而.NET Core 3.1可能不仅仅限制了GroupBy,也许还限制了List传递到前台的可能性。
像ToListAsync()这样的方法,在我的前台页面是行不通的。
但是,新的疑惑出现了,return View(await BlogsModel.ToListAsync());是我照着HomeController等基架原生出来的代码写的,而用基架生成的页面没有任何错误,我写的页面却报错了…… 难道我们用的不是同一个EntityFrameworkCore吗?
暂时没有解决方案,等 .NET 5.0 。
Today's comments have reached the limit. If you want to comment, please wait until tomorrow (UTC-Time).
There is 18h40m04s left until you can comment.