(已解决:见底部)
我有以下代码段:
Protected Sub SqlDataSource1_Inserted(ByVal sender As Object,
ByVal e As System.Web.UI.WebControls.SqlDataSourceStatusEventArgs)
Handles SqlDataSource1.Inserted
affected = CInt(DirectCast(e.Command.Parameters("@affected"), IDbDataParameter).Value)
newID = CInt(DirectCast(e.Command.Parameters("@newID"), IDbDataParameter).Value)
End Sub
其中@newID在SQL字符串中定义如下:
"INSERT INTO x(a,b,c) VALUES (@a,@b,@c); SELECT @affected = @@rowcount, @newID = SCOPE_IDENTITY();
使用ASP.NET定义参数如下:
关于它的奇怪之处在于它在90%的时间内都有效,但每次都会抛出一个InvalidCastException,说“从类型'DBNull'转换为'Integer'类型无效。”关于什么可能导致这个值为null的任何想法?我没有在表上设置任何触发器,我的查询唯一做的就是在1个表中运行普通插入。
修改:根据此处的建议,我添加了affected
参数。我设置了一个断点,并且受影响= 1但我仍然有例外。但是,我在SELECT @affected之前发现我有SELECT @newID。我切换了顺序,现在@affected = 0.所以看来我的插入语句出现了问题。谢谢你的帮助!
答案 0 :(得分:8)
来自MSDN
INSERT,SELECT INTO或bulk之后 复制声明完成, @@ IDENTITY包含最后一个身份 由...生成的值 声明。如果声明没有 影响任何具有身份的表 列,@ @ IDENTITY返回NULL。
您是否检查插件是否成功?您尝试插入的记录可能由于某种原因无法插入任何内容,因此id为null。
桌子上是否设置了任何触发器?您可能正在使用@@ IDENTITY
从触发器过程中检索id我建议您使用SCOPE_IDENTITY()或output parameter来获取ID
答案 1 :(得分:4)
在99.9%的案例中,您应该使用SCOPE_IDENTITY()
作为@@IDENTITY
的反对者。您的情况非常罕见,需要SCOPE_IDENTITY()
@@IDENTITY
返回最后一个IDENTITY 连接上产生的值, 不管生产的表格如何 价值,而不论范围 产生的声明 值。如果你有一个触发器 导致身份的表 在另一个表中创建,你会得到 最后创建的身份, 即使它是触发器 创造了它。
SCOPE_IDENTITY()
返回a上生成的最后一个IDENTITY值 连接和通过声明 相同的范围,无论表格如何 产生了价值。 SCOPE_IDENTITY(),如@@ IDENTITY, 将返回最后一个标识值 在当前会话中创建,但它 也将它限制在你当前 范围也是如此。
您确定该表上没有审核触发器(可能由您的DBA添加)吗?
答案 2 :(得分:2)
各种可能性:
INSERT不会插入任何内容(如 erikkallen说)
您的陈述(未显示)插入 各种表,最后一个 没有身份 柱
INSERT触发一个触发器 插入到没有的表 标识栏 - 试试 SCOPE_IDENTITY()改为
答案 3 :(得分:1)
您可能需要检查@@ ROWCOUNT> 0
在过去的SQL Server版本中也存在已知问题,其中触发器会影响@@ IDENTITY的生存能力。你有任何触发器吗?
答案 4 :(得分:1)
另一次发生这种情况,改变
<asp:Parameter Name="newID" Direction="Output" Size="4" />
到
<asp:Parameter Name="newID" Direction="Output" Type="Int32" Size="4" />
为我解决了这个问题。看来我的主持人提出了更明确的声明要求。
答案 5 :(得分:0)
query text...
部分是什么?我猜是INSERT。
可能是insert ... select
找不到任何行吗?
答案 6 :(得分:0)