我正在将 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
有没有办法允许此功能在不更改它的情况下运行?如果没有,我将如何解决它?
您的问题是以下行:
Dim m = 0
我怀疑它在VS2005中工作的原因是因为Option Strict
被关闭了,所以m
的类型默认为Object
。 换句话说,在VS2005中,对于Option Strict Off
,上面的行将等效于:
Dim m As Object = 0
如果m
是一个对象,则它引用的任何值都将被装箱,因此将允许Is
操作。 但是,在您的VS2008项目中,我怀疑Option Infer
已打开(该功能在2005年不存在),因此m
的类型在编译时被推断为Integer
,因为您将其设置为整数文字(Dim m = 0
)。 换句话说,在VS2008中,Option Infer On
上述行将等效于:
Dim m As Integer = 0
由于它被声明为Integer
类型,而不是Object
类型,因此您不能再使用Is
运算符。 有关此内容的详细信息,请参阅 MSDN 的此页,其中给出了此示例:
点心数量 = 5
- 如果选项推断处于打开状态(默认值),则变量采用初始值设定项的数据类型。请参阅本地类型推断 (Visual Basic)。
如果"选项推断"处于关闭- 状态,而"选项严格"处于关闭状态,则该变量将采用"对象"的数据类型。
- 如果"选项推断"处于关闭状态,而"选项严格"处于打开状态,则会发生编译时错误。
解决此问题的最简单方法是简单地打开Option Infer Off
,以便它以与VS2005相同的方式编译。 但是,如果要保留Option Infer On
并改为修复代码,则需要指定变量类型,如下所示:
Dim x As Object = 0
您可能认为可以通过更改检查是否m Is DBNull
的方式来修复它。 例如,将编译以下任一行:
If Convert.IsDBNull(m) Then
或:
If TypeOf m Is DBNull Then
但是,您会注意到这两个If
语句都不会计算为 true。如果m
被声明为Integer
,那么它就永远不能被DBNull
。 如果数据库中的列等于 null,则以下行将引发异常,因为它会尝试将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
,可以暂时打开Option Infer Off
并打开Option Strict On
。 当 Option Strict
打开且Option Infer
关闭时,除非始终指定所有变量类型,否则项目将不会编译。
您可以使用类似以下内容在数据库查询阶段消除该问题
SELECT COALESCE(MAX(" & f & "), 0) AS max FROM " & t
然后无条件地递增 m。
此外,您可以使用ExecuteScalar而不是ExecuteReader,因为您只得到一个值。
只需使变量 m nullabale
Dim m As Nullable(Of Integer)