【发布时间】:2009-09-03 05:47:06
【问题描述】:
我的插入存储过程:
ALTER procedure proj_ins_all
(
@proj_number INT,
@usr_id INT,
@download DATETIME,
@status INT
)
as
INSERT INTO project
(proj_number, usr_id, date_download, status_id)
VALUES
(@proj_number, @usr_id, @download, @status)
select SCOPE_IDENTITY()
... 像这样手动调用时运行良好:
exec proj_ins_all 9001210, 2, '2009-09-03', 2
...但是当从代码中调用时:
_id = data.ExecuteIntScalar("proj_ins_all", arrParams);
...插入不会发生。现在,标识列 does 增加,_id does 设置为它的值。但该行本身从未出现在表中。
我能想到的最好的猜测是一个插入触发器,它删除了新插入的行,但表上没有触发器(为什么手动完成它会起作用?)。我的其他尝试是围绕存储过程以某种方式回滚插入的猜测,因此将 begin 和 end 和 go 的和分号到存储过程中以正确分隔“插入”和“身份选择”位。这没有解决任何问题。
有什么想法吗?
更新:
感谢迄今为止提供帮助的所有人。根据 Preet 的建议(第一个答案),我学会了如何使用 SQL Server Profiler(我不敢相信我以前从来不知道它 - 我认为它只对性能调整有用,没有意识到我可以确切地看到查询正在发生什么到数据库)。
它显示 SqlCommand.ExecuteScalar() 方法发送的 SQL 与我手动运行的略有不同。它正在发送:
exec proj_ins_all @proj_number=9001810,@usr_id=2,@download='2009-09-03 16:20:11.7130000',@status=2
我手动运行了它,瞧!一个实际的 SQL 服务器错误(!):
将数据类型 varchar 转换为 datetime 时出错。
由于我是手动测试的,我只是将日期时间从 '2009-09-03 16:20:11.7130000' 缩短为 '2009-09-03 16:20:11 ' 这修复了错误;现在该行插入正常。
但这引出了一个问题:为什么 Microsoft 的 SQL Server 不能在该日期时间参数中处理超过 23 个字符?是微软的 SqlCommand.ExecuteScalar() 方法构造了这样的查询,而不是我。这是一个问题,因为我的代码仍然无法运行。
当我手动让它工作时,我研究了如何在代码中为日期设置 SqlParameter,以便它发送一个与有效值类似的值。我尝试将数据类型从 SqlDbType.DateTime 更改为 SqlDbType.SmallDateTime。分析器显示这确实产生了更短的日期时间值“2009-09-03 17:15:00”,但插入仍然默默失败(原始问题)。但是,当我从探查器复制粘贴 sql 并手动尝试时 - 它起作用了。没有错误。发送它作为 varchar 的相同交易 - SSMS 查询窗口喜欢它,通过 .net 的相同查询静默失败。
:(
还有其他想法吗? SQL 服务器中的一些“环境”类型设置,例如“set ansi_nulls off”或手动连接和直通代码连接之间可能不同的任何设置?
(还有一个问题是为什么每次出现这个错误时sql server不给我错误信息并产生异常?)
.Net 代码
根据 van 的要求,这里是相关的 .NET 代码(C# ASP.NET):
data.MakeInParam("@proj_number", SqlDbType.Int, _projNo),
data.MakeInParam("@usr_id", SqlDbType.Int, _usr.Id),
data.MakeInParam("@download", SqlDbType.SmallDateTime, _downloadDate),
data.MakeInParam("@status", SqlDbType.Int, (int)_status),
并且 MakeInParam 有这一行:
param = new SqlParameter(paramName, DbType);
它会像这样执行:
SqlCommand cmd = CreateCommand(procName, prams);
object result = cmd.ExecuteScalar();
注意:在上面的参数中,@download 是问题所在。 _downloadDate 是一个可为空的日期时间。请注意,此行中的 sql 类型曾经是 SqlDbType.DateTime,但我将其更改为 SqlDbType.SmallDateTime 以生成手动调用(从代码运行时仍然失败)。
更新:已解决 感谢马特,我终于找到并解决了这个问题:自定义助手类在它的一个函数中缺少一个 cmd.Transaction.Commit() !它里面有一堆不同的乱七八糟的东西,我在最初浏览代码时错过了这一点。
感谢 Matt 和 Preet 以及其他所有做出贡献的人。
经验教训
- SQL Profiler 真的很有用。花点时间学习如何使用它。
- 如果数据库正在吞噬错误,或者似乎正在根据您的代码执行某些操作,但实际上并没有出现在数据库中,请检查事务是否正在提交。
- 不要太相信别人写的数据库助手类。即使是一开始看起来很简单的一个。确保您完全了解它的作用,因为它可能有问题,或者只是没有按照您认为的方式做事。
【问题讨论】:
标签: .net sql sql-server ado.net