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

这几天,客户报告了一个Bug,  经过跟踪,发现是下面linq语句引起的,

manuLines = CustomerDBContext.Bookkeeping_Netvisor_PurchaseInvoicesLines.Where(Function(pil) pil.PIL_PI_SysID = sysID).ToList()

它会抛出一个转换异常: unable to cast object of type "System.Int32" to "System.String", 然后在堆栈里追踪到其中一步是 SqlDataReader.get_string()...

这个程序已经跑了很久,一直没有问题, Bookkeeping_Netvisor_PurchaseInvoicesLines 是一个视图, 我跟踪Runtime执行这句后生成的sql, 把它拿到查询分析器里执行,也没有问题,看了数据类型的匹配,还是没有问题, 百思不得其解! 

偶然, 我把视图删除了,用一样的语句重建,它又正常工作了, 于是我推断是数据库表结构变化,引起视图的结构推断问题。 我重新把数据库恢复到删除视图并重建前, 并调用 sp_refreshView 'Bookkeeping_Netvisor_PurchaseInvoicesLines' ,发现也能解决问题。  后来终于在微软 MSDN文章中找到正解:

http://msdn.microsoft.com/zh-cn/library/ms187821.aspx ,

大致意思是说:在创建视图时,如果没有用 with schemabinding 关键字

则视图相关联表结构的变化可能导致视图结构推断出错。 解决方案是一个个调用 sp_refreshView '视图名' 刷新相关联视图。

需要注意的是,如果要在视图上创建索引, 也需要在创建视图时使用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)

原文地址:https://www.cnblogs.com/Hcsdn/p/2916712.html