【问题标题】:Why does rowsAffected return 0 when I have passed parameters for it to use?为什么当我传递参数供它使用时,rowsAffected 返回 0?
【发布时间】:2019-11-28 11:27:00
【问题描述】:

我正在尝试使用 SQL 过程和 MVC 控制器将数据插入数据库。我有使用 HTML 表单获取的数据,然后由 Create 方法检索并添加到 SQL 过程的参数中。

 public ActionResult Create([Bind(Include = "UserID,FirstName,Surname,Password,Salt,Phone_Number,Email,IsAdmin")] SaltUsersTable saltUsersTable, FormCollection fc)
        {
            if (ModelState.IsValid)
            {
                SqlConnection con = new SqlConnection(@"Connection String");
                SqlCommand cmd = new SqlCommand();

                cmd.CommandText = "dbo.AddSaltedUser";
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Connection = con;

                cmd.Parameters.Add("@Password", SqlDbType.NVarChar, 50).Value = Request.Form["Password"];
                cmd.Parameters.Add("@FirstName", SqlDbType.NVarChar, 50).Value = Request.Form["FirstName"];
                cmd.Parameters.Add("@Surname", SqlDbType.NVarChar, 50).Value = Request.Form["Surname"];
                cmd.Parameters.Add("@Email", SqlDbType.NVarChar, 100).Value = Request.Form["Email"];
                cmd.Parameters.Add("@PhoneNumber", SqlDbType.NVarChar, 12).Value = Request.Form["PhoneNumber"];

                cmd.Parameters.Add("@response", SqlDbType.NVarChar, 250).Direction = ParameterDirection.Output;

                if (Request.Form["FirstName"] == "Admin")
                {
                    cmd.Parameters.Add("@IsAdmin", SqlDbType.Bit).Value = 1;
                }
                else
                {
                    cmd.Parameters.Add("@IsAdmin", SqlDbType.Bit).Value = 0;
                }

                //Execute the command just established
                con.Open();
                Int32 rowsAffected = cmd.ExecuteNonQuery();
                con.Close();

上面显示的代码是创建控制器(我已经替换为通用的连接字符串)

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

 ALTER PROCEDURE [dbo].[AddSaltedUser]
    @FirstName NVARCHAR(50),
    @Surname NVARCHAR(50),
    @Password NVARCHAR(50),
    @PhoneNumber NVARCHAR(12),
    @Email NVARCHAR(50),
    @IsAdmin BIT,
    @response NVARCHAR(250) OUTPUT
AS 

BEGIN
    SET NOCOUNT ON

    DECLARE @salt UNIQUEIDENTIFIER=NEWID()
    BEGIN TRY

        INSERT INTO dbo.SaltUsersTable (FirstName, Surname , Password, PhoneNumber, Email, IsAdmin)
        VALUES(@FirstName, @Surname, HASHBYTES('SHA_512',@Password+CAST(@salt AS NVARCHAR(36))), @PhoneNumber, @Email, @IsAdmin)

        SET @response='Success'
    END TRY
    BEGIN CATCH
        SET @response='ERROR'
    END CATCH
END

这段代码是我编写的 SQL 过程,它应该插入从 MVC 控制器传递的参数,除了在过程中完成的加盐哈希。

此代码的问题在于它实际上不会向数据库中插入任何内容。当我运行代码并在 rowsAffected 有一个断点时,它显示它是 0,我不知道为什么。这段代码我哪里出错了?

但是我应该说参数确实存在,并且在控制器中正确收集了表单值,因为我已经使用调试器完成了它。

【问题讨论】:

  • @Corey SET NOCOUNT ON 不会“停止服务器计算受影响的行”,它会停止将其返回给客户端。使用 SET NOCOUNT ON 你不能得到“0行受影响”,你什么也得不到
  • 在你的 catch 块中添加 throw;它会将错误抛出到您的客户端代码中
  • 你是如何检查该行是否被插入的?通过查询表或仅检查您的 rowsAffected?
  • @sepupic 我查询了表的前 200 行,它为每一列返回一行 NULL。
  • 这意味着不是“它实际上不会向数据库中插入任何内容”而是“它会插入空值”,您应该编辑您的问题,因为您真正的问题是“为什么我的代码插入空值”,它似乎问题不在服务器端,是你的 c# 代码传递了一些奇怪的东西

标签: c# sql-server model-view-controller ado.net


【解决方案1】:

这里的问题可能是@IsAdmin 参数吗?

您正在使用数据类型 SqlDbType.Bit(参数也是 BIT)据我所知仅接受 0/1/NULL 并且您将值设置为 true/false。我知道有时真/假 0/1 是可以互换的,但我不确定 C# 将如何通过它,如果这不是问题,但这是一回事。

相关问题:DbType equivalent to SqlDbType.Bit

【讨论】:

  • 抱歉没有编辑我在等待回答我的问题时设法抓住了这一点。不过感谢您的意见。
【解决方案2】:

问题是您的存储过程中有一个SET NOCOUNT ON 语句。来自the docs

停止显示受 Transact-SQL 语句或存储过程影响的行数的消息作为结果集的一部分返回。

它完全按照您的指示去做。注释掉 SP 中的那一行,它将返回受影响的行数:1 表示插入成功,0 表示失败。


至于你的行没有插入...

在您的插入中,您使用的 HASHBYTES 算法无效。这会导致所有输入的 null 值。尝试用'SHA2_512' 替换您的SP 中的'SHA_512',它会给您带来更好的结果。

虽然这可能是导致未插入行的原因,但您无法找出所有已禁用的错误。 TRY...CATCH 在代码中的这一点通常不是一个好主意,因为它会抑制所有那些方便的错误消息,否则这些错误消息可能会告诉你出了什么问题。

我创建了一个测试表并使用了您的代码(具有正确的散列算法名称),它对我来说效果很好。我假设您的表上有一个约束——例如密码字段上的唯一索引——这会阻止添加记录。

作为一个兴趣点,您确实知道随机盐值会使它完全无法使用,对吧?即使在示例代码中,最好用明显的非生产值表示你的盐,比如'stand-in the real salt value' 或其他东西。

【讨论】:

  • 在您发布的引文中说明了我所说的“停止返回的消息”,而不是您所说的,它停止计数
  • @sepupic 阅读全文“停止消息显示受影响行数的计数...”请注意,我删除了我之前的评论并更正了我的声明.
  • @Corey 从程序中删除它仍然不允许我将数据输入到表中并保持空白。你知道我将如何编辑它的代码以允许我输入数据吗?抱歉,如果我的问题不清楚,这已经困扰了我一段时间。
  • @Corey 好的,现在听起来好多了。当我在答案下写评论时,您的第一条评论仍然存在
  • >>>TRY...CATCH 通常是一个坏主意,因为它会抑制所有方便的错误消息
猜你喜欢
  • 2014-06-05
  • 1970-01-01
  • 2019-09-03
  • 1970-01-01
  • 2019-10-10
  • 2012-04-24
  • 1970-01-01
  • 2018-06-01
  • 2019-06-24
相关资源
最近更新 更多