数据库表结构变化引起视图字段类型推断错误

Posted 用CSharp学Python

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据库表结构变化引起视图字段类型推断错误相关的知识,希望对你有一定的参考价值。

阅读本文需要两分钟

当前浏览器不支持播放音乐或语音,请在微信或其他浏览器中播放

前因

今天看以前的代码报一个很明显的错,但就是一直解决不了,前后被折腾了三个小时才找到原因,因此记录一下。

如下图,代码执行到ToList()就会跳到异常,单点到这个地方的时候,异常信息就是unable to cast object of type "System.String" to "System.Int32",其实看到这个报错是非常明显的,就是转换类型报错,查询出的数据库类型,与在代码的中实体类的类型不能匹配上,类型转换失败导致的。
因此这个时候我就是以为对比一下实体类的数据类型以及对应表字段类型就可以了。于是我就开始掉坑。。。

因为在我反复认真对比四五次字段类型后,我能百分百肯定我这个视图表的类型跟实体类的类型是完全相同,但就是想不明白为什么这个数据一直转换失败。
这时候我还怀疑过是不是某些null值影响导致,因为曾经我被的一个数据库里的bit类型为null也导致过掉了一个类似的坑。
不过经过一翻试验后,是可以我这里是排除null的影响的,具体就不说,况且这里的报错其实也是很明显的,就是装拆箱问题。

解决方案

最后,经过一番研究后发现其实是我这个视图没有更新的原因!!
因为前段时间因为需求原因我将这个视图用来的表的一个字段类型由int转换成nvarchar,当时我将关于这个表的在代码中的使用都检查过,但是忽略了还是视图引用。从而我对比数据库视图字段,本身就是旧的,跟数据库内的字段都对不上,因此一直都对比不出来。

更新视图的方法:

  • 1. 删除原视图,然后原语句重新创建 (这样其实很麻烦,不推荐)

  • 2.使用sql server自带的存储过程sp_refreshView更新视图,使用方法:sp_refreshView 'view_test'(推荐)
    下面这个是关于这个存储过程的官方介绍
    https://docs.microsoft.com/zh-cn/sql/relational-databases/system-stored-procedures/sp-refreshview-transact-sql?redirectedfrom=MSDN&view=sql-server-ver15

根本原因:
其实导致这个问题发生的根本原因就是,我们创建视图的视图的时候没有带上 with schemabinding关键字,视图就不会随表更新,一直保持在创建时候表的状态。

需要注意的是,如果要在视图上创建索引, 也需要在创建视图时使用with schemabinding 关键字。

在视图上创建索引是有一定的限制的。如楼主所说,要在视图上创建索引,
视图定义的时候要包含WITH SCHEMABINDING选项,
另外必须在视图上创建一个唯一聚集索引以后才可以创建非聚集索引。

CREATE TABLE dbo.Test(a int,b int)
GO
CREATE VIEW vTest WITH SCHEMABINDING
AS
SELECT a,b
FROM dbo.Test
GO
CREATE UNIQUE CLUSTERED INDEX IX_vTest_a ON vTest(a)
--注意,由于是唯一性索引,如果基表Test的a列包含重复值的话索引是不能创建成功的
GO 
--再创建一个非聚集索引
CREATE INDEX IX_vTest_b ON vTest(b)

以上是关于数据库表结构变化引起视图字段类型推断错误的主要内容,如果未能解决你的问题,请参考以下文章

在片段中创建自定义列表视图时出错。必需的活动,找到的片段

HBase源代码分析之MemStore的flush发起时机推断条件等详情

mysql 当视图 view_a 得到的数据变化后,实表 table_a 如何同步数据?

Swift 2.0:推断闭包类型错误

错误:类型不匹配:推断类型为单位,但应为布尔值

使用Mybatis继承特性应对数据库变化