前因
今天看以前的代碼報一個很明顯的錯脂矫,但就是一直解決不了,前后被折騰了三個小時才找到原因霉晕,因此記錄一下庭再。
如下圖,代碼執(zhí)行到ToList()就會跳到異常牺堰,單點(diǎn)到這個地方的時候拄轻,異常信息就是unable to cast object of type "System.String" to "System.Int32"
,其實(shí)看到這個報錯是非常明顯的,就是轉(zhuǎn)換類型報錯伟葫,查詢出的數(shù)據(jù)庫類型恨搓,與在代碼的中實(shí)體類的類型不能匹配上,類型轉(zhuǎn)換失敗導(dǎo)致的筏养。
因此這個時候我就是以為對比一下實(shí)體類的數(shù)據(jù)類型以及對應(yīng)表字段類型就可以了奶卓。于是我就開始掉坑。撼玄。。
因為在我反復(fù)認(rèn)真對比四五次字段類型后墩邀,我能百分百肯定我這個視圖表的類型跟實(shí)體類的類型是完全相同掌猛,但就是想不明白為什么這個數(shù)據(jù)一直轉(zhuǎn)換失敗。
這時候我還懷疑過是不是某些null值影響導(dǎo)致眉睹,因為曾經(jīng)我被的一個數(shù)據(jù)庫里的bit類型為null也導(dǎo)致過掉了一個類似的坑荔茬。
不過經(jīng)過一翻試驗后,是可以我這里是排除null的影響的竹海,具體就不說慕蔚,況且這里的報錯其實(shí)也是很明顯的,就是裝拆箱問題斋配。
解決方案
最后孔飒,經(jīng)過一番研究后發(fā)現(xiàn)其實(shí)是我這個視圖沒有更新的原因9喙搿!
因為前段時間因為需求原因我將這個視圖用來的表的一個字段類型由int轉(zhuǎn)換成nvarchar坏瞄,當(dāng)時我將關(guān)于這個表的在代碼中的使用都檢查過桂对,但是忽略了還是視圖引用。從而我對比數(shù)據(jù)庫視圖字段鸠匀,本身就是舊的蕉斜,跟數(shù)據(jù)庫內(nèi)的字段都對不上,因此一直都對比不出來缀棍。
更新視圖的方法:
- 刪除原視圖宅此,然后原語句重新創(chuàng)建 (這樣其實(shí)很麻煩,不推薦)
- 2.使用sql server自帶的存儲過程
sp_refreshView
更新視圖爬范,使用方法:sp_refreshView 'view_test'
(推薦)
下面這個是關(guān)于這個存儲過程的官方介紹
https://docs.microsoft.com/zh-cn/sql/relational-databases/system-stored-procedures/sp-refreshview-transact-sql?redirectedfrom=MSDN&view=sql-server-ver15
根本原因:
其實(shí)導(dǎo)致這個問題發(fā)生的根本原因就是父腕,我們創(chuàng)建視圖的視圖的時候沒有帶上 with schemabinding
關(guān)鍵字,視圖就不會隨表更新坦敌,一直保持在創(chuàng)建時候表的狀態(tài)侣诵。
需要注意的是,如果要在視圖上創(chuàng)建索引狱窘, 也需要在創(chuàng)建視圖時使用with schemabinding
關(guān)鍵字
在視圖上創(chuàng)建索引是有一定的限制的杜顺。如樓主所說,要在視圖上創(chuàng)建索引蘸炸,
視圖定義的時候要包含WITH SCHEMABINDING選項躬络,
另外必須在視圖上創(chuàng)建一個唯一聚集索引以后才可以創(chuàng)建非聚集索引。
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列包含重復(fù)值的話索引是不能創(chuàng)建成功的
GO
--再創(chuàng)建一個非聚集索引
CREATE INDEX IX_vTest_b ON vTest(b)