我正在将一个VB2005 Web应用程序移植到VB2008,并遇到编译问题。
当我尝试编译项目时,问题就出现了,我收到了这个错误:
If m Is DBNull.Value...
错误:
'Is' operator does not accept operands of type 'Integer'.
Operands must be reference or nullable types.
代码:
Public Shared Function getNextID(ByVal t As String, ByVal f As String)
Dim m = 0
Dim c As New Data.SqlClient.SqlConnection
c = getConn()
c.Open()
Dim s As String
s = "SELECT MAX(" & f & ")AS max FROM " & t
Dim q As New Data.SqlClient.SqlCommand(s, c)
Dim r = q.EmecuteReader
While r.Read
m = r.GetValue(0)
End While
If m Is DBNull.Value Then
m = 1
Else
m += 1
End If
r = Nothing
q = Nothing
c.Close()
c = Nothing
Return m
End Function
有没有办法让这个功能在不改变的情况下运行?如果没有,我该如何解决?
答案 0 :(得分:3)
您的问题如下:
Dim m = 0
我怀疑它在VS2005中工作的原因是因为Option Strict
被关闭,所以m
的类型默认为Object
。换句话说,在VS2005中,使用Option Strict Off
,上面的行将相当于:
Dim m As Object = 0
如果m
是一个对象,那么它引用的任何值都将装箱,因此允许Is
操作。但是,在您的VS2008项目中,我怀疑Option Infer
已打开(2005年不存在的功能),因此m
的类型在编译时被推断为{{1}因为你将它设置为整数文字(Integer
)。换句话说,在VS2008中,使用Dim m = 0
,上面的行将等同于:
Option Infer On
由于它被声明为Dim m As Integer = 0
类型而不是Integer
类型,因此您不能再使用Object
运算符了。有关此内容的更多信息可以在MSDN的this page上找到,其中给出了此示例:
Dim qty = 5
- 如果启用了Option Infer(默认值),则变量将采用初始化程序的数据类型。请参阅本地类型推断(Visual Basic)。
- 如果Option Infer关闭且Option Strict关闭,则变量采用Object的数据类型。
- 如果Option Infer已关闭且Option Strict已启用,则会发生编译时错误。
解决问题的最简单方法是简单地转动Is
,使其以与VS2005相同的方式进行编译。但是,如果您要离开Option Infer Off
,而是修改代码,则需要指定变量类型,如下所示:
Option Infer On
您可能认为可以通过更改检查Dim x As Object = 0
的方式来解决此问题。例如,以下任一行都将编译:
m Is DBNull
或者:
If Convert.IsDBNull(m) Then
但是,您会注意到这两个If TypeOf m Is DBNull Then
语句都不会评估为true。如果If
被声明为m
,那么它永远不会是Integer
。如果数据库中的列等于null,则以下行将抛出异常,因为它会尝试将DBNull
对象强制转换为DbNull
,这是不可能的:
Integer
m = r.GetValue(0) ' This will throw exception if column is null and m is an integer
变量支持等于m
或Integer
对象的唯一方法是将其声明为DbNull
。
如果项目有很多没有指定类型的地方,就像这样,你应该关闭Object
。如果您想找到问题所在的所有地方,以便您可以在代码中修复所有问题,然后重新启用Option Infer
,则可以暂时转为Option Infer
并转为{{ 1}}。当Option Infer Off
打开且Option Strict On
关闭时,除非始终指定所有变量类型,否则项目将无法编译。
答案 1 :(得分:0)
您可以使用类似
的方法消除数据库查询阶段的问题SELECT COALESCE(MAX(" & f & "), 0) AS max FROM " & t
然后无条件地增加m。
此外,您可以使用ExecuteScalar而不是ExecuteReader,因为您只获得一个值。
答案 2 :(得分:0)
只需将你的变量设为nullabale
Dim m As Nullable(Of Integer)