System.Data.SqlClient.SqlException: '将 nvarchar 值 'STORES' 转换为数据类型 int 时转换失败'

问题描述

我正在 C# asmx web 服务中执行存储过程。 存储过程如下:

@userName NVARCHAR(50),@password NVARCHAR(50),@defaultTabApp NVARCHAR(20) OUT
AS
Declare @defaultTabApptemp NVARCHAR(20)
set @defaultTabApptemp ='NoAccess'
BEGIN TRANSACTION
    if EXISTS(SELECT Top 1  [userId],[userName] FROM [dbo].[users] WHERE [userName]=@userName AND [password]=@password AND [AppAccess]=N'Yes') 
    Begin
       set @defaultTabApptemp = (select Top 1 [dbo].[users].[defaultTabApp] FROM [dbo].[users] WHERE [userName]=@userName AND [password]=@password AND [AppAccess]=N'Yes')
    end
 select @defaultTabApp =  @defaultTabApptemp 

COMMIT TRANSACTION
return @defaultTabApp

我的 C# 代码是:

[WebMethod]
        public string Login(string userName,string userPass)
        {
            string result;
            sqlConnection conn = new sqlConnection(new DBConnection().ConnectionString);
           
            try
            {

                sqlCommand cmd = new sqlCommand("_getSpecificUserLogin",conn);
                cmd.CommandType = System.Data.CommandType.StoredProcedure;
                
                if (conn.State == System.Data.ConnectionState.Closed)
                {
                    conn.open();
                }
                
                cmd.Parameters.AddWithValue("@userName",userName);
                cmd.Parameters.AddWithValue("@password",userPass);
               

                cmd.Parameters.Add("@defaultTabApp",sqlDbType.NVarChar,20);
                cmd.Parameters["@defaultTabApp"].Direction = ParameterDirection.Output;
                int i = cmd.ExecuteNonQuery();
                result = Convert.ToString(cmd.Parameters["@defaultTabApp"].Value);

            }


            finally
            {
                conn.Close();
            }
            return result;
}

我在此行的标题中发现异常:int i = cmd.ExecuteNonQuery(); 我试图将其更改为 executescalar,但遇到了同样的问题。我的存储过程中没有 int 类型。究竟是什么问题?提前致谢。

解决方法

您的登录过程的基本框架应如下所示。

请注意,您不需要事务,也不需要先检查是否存在任何内容 - 这暗示了它为您的输出变量分配了一个值。

您的代码无法处理密码错误或用户没有启用应用的情况。

实际上,您会首先验证用户并为他们分配某种票证以表明他们已成功登录并且不会反复检查他们的密码;当需要获取他们的默认应用时,他们已经通过了身份验证。

如果您可以让一个用户拥有多个 appAccess='Yes',则您只需要前 1,在这种情况下,您将缺少选择正确的排序标准 - 没有特定的 order 子句,该值本质上是随机的。

输出参数的正确语法是 Output

我还希望,如果这是一个面向公众的应用程序,密码不是纯文本,而是作为用户密码的哈希存储在数据库中。

create procedure UserLogin
@userName nvarchar(50),@password nvarchar(50),-- This should be a HASH of the user's password,performed by the application
@defaultTabApp nvarchar(20) output
as
set nocount on
set @defaultTabApp='Default failure message'

select top 1 @defaultTabApp=defaultTabApp
from dbo.Users
where AppAccess=N'Yes'
    and Username=@userName and [Password]=@password 
order by <<criteria if there are more than 1 matching rows>>
Go
,

RETURN 只能返回 int。您已经使用了 OUT 参数,您应该删除存储过程末尾的 return @defaultTabApp 语句。

,

替换

Declare @defaultTabApptemp NVARCHAR(20)
set @defaultTabApptemp ='NoAccess'
BEGIN TRANSACTION
    if EXISTS(SELECT Top 1  [userId],[userName] FROM [dbo].[users] WHERE [userName]=@userName AND [password]=@password AND [AppAccess]=N'Yes') 
    Begin
       set @defaultTabApptemp = (select Top 1 [dbo].[users].[defaultTabApp] FROM [dbo].[users] WHERE [userName]=@userName AND [password]=@password AND [AppAccess]=N'Yes')
    end
 select @defaultTabApp =  @defaultTabApptemp 

COMMIT TRANSACTION
return @defaultTabApp

Declare @defaultTabApptemp NVARCHAR(20)

 select Top 1  @defaultTabApptemp=[dbo].[users].[defaultTabApp] FROM [dbo].[users] 
WHERE [userName]=@userName AND [password]=@password AND [AppAccess]=N'Yes')
 if @defaultTabApptemp is null  SET @defaultTabApptemp ='NoAccess'
set @defaultTabApp =  @defaultTabApptemp