Вернуть одну строку из хранимой процедуры в asp.net - PullRequest
1 голос
/ 20 августа 2011

Я создаю хранимую процедуру для извлечения одной строки в таблице:

create procedure LogInUser
    @username nvarchar(64),
    @password nvarchar(64),
    @succeed bit out,   
    @not_exist_err bit out
as
declare @exist_user nvarchar(64)
select @exist_user = username from users
where username = @username

if @exist_user is null
begin
    set @succeed = 0
    set @not_exist_err = 1
    return
end
else
begin
    select * from users
    where username = @username and password = @password 
end
return

Сначала я проверяю, существует пользователь или нет, используя:

select @exist_user = username from users
where username = @username

Затемполучить строку с каждым столбцом:

select * from users
where username = @username and password = @password 

Однако, используя SqlDataReader, программа не войдет в цикл while для получения информации.

Она просто не вводитсяпетля.Я не понимаю, почему, даже если я выполнил его с использованием SQL Server следующим образом, он вернул строку:

declare @succeedResult bit
declare @existErr bit
exec LogInUser @username=admin, @password =admin, @succeed = @succeedResult, @not_exist_err = @existErr

EDIT : метод C #, который выполняет процедуру сохранения:

public User LogIn(User usr)
{
   SqlConnection conn = A2.Controller.Utils.conn;
   SqlCommand loginCmd = new SqlCommand("LogInUser", conn);
   loginCmd.CommandType = CommandType.StoredProcedure;

   User result = new User();

   try
   {
       conn.Open();
       loginCmd.Parameters.Add("@username", SqlDbType.NVarChar).Value = usr.Username;
       loginCmd.Parameters.Add("@password", SqlDbType.NVarChar).Value = usr.Password;
       loginCmd.Parameters.Add("@succeed", SqlDbType.Bit).Direction = ParameterDirection.Output;
       loginCmd.Parameters.Add("@not_exist_err", SqlDbType.Bit).Direction = ParameterDirection.Output;                
       SqlDataReader dr = loginCmd.ExecuteReader();              

       if (loginCmd.Parameters["@succeed"].Value != DBNull.Value){
          Console.WriteLine("User does not exist");
          SqlParameter notExistErr = loginCmd.Parameters["@not_exist_err"];

          if (notExistErr.Value != DBNull.Value){
             throw new NotExistException("The username or password is incorrect.", "Users");
          }
       }

       while (dr.Read()) {
           Console.WriteLine("Looping dr");
           result.Username = (string) dr["username"];
           result.Password = (string) dr["password"];
           result.FirstName = (string) dr["first_name"];
           result.MiddleName = (string) dr["middle_name"];
           result.LastName = (string) dr["last_name"];
           result.ManagerID = (int) dr["manager_id"];
           result.IsAdmin = (int) dr["is_admin"];

           return result;
        }
        Console.WriteLine("Done reading");
    }             
    finally {
       if (conn.State == ConnectionState.Open) conn.Close();
    }
    return result;
 }

Ответы [ 3 ]

2 голосов
/ 20 августа 2011

Выходные параметры заполняются только после прочтения последней строки из последнего результирующего набора в процедуре. Так что эта часть не будет работать:

SqlDataReader dr = loginCmd.ExecuteReader();              
if (loginCmd.Parameters["@succeed"].Value != DBNull.Value){

На данный момент loginCmd.Parameters["@succeed"].Value не установлено: оно будет установлено только после того, как вы прочитали последнюю строку, и dr.Read() вернул false.

Не рекомендуется использовать параметры output в хранимых процедурах, которые возвращают наборы строк.

1 голос
/ 20 августа 2011

Вы можете проверить, возвращает ли ваш запрос результат или не использует dr.HasRows, и он должен выглядеть следующим образом ...

SqlDataReader dr = loginCmd.ExecuteReader();              
if (!dr.HasRows)
{
    Console.WriteLine("User does not exist");
    SqlParameter notExistErr = loginCmd.Parameters["@not_exist_err"];
    if (notExistErr.Value != DBNull.Value)
    {
        throw new NotExistException("The username or password is incorrect.", "Users");
    }
}
else
{
    while (dr.Read())
    {
        Console.WriteLine("Looping dr");
        result.Username = (string) dr["@username"];
        result.Password = (string) dr["@password"];
        result.FirstName = (string) dr["@first_name"];
        result.MiddleName = (string) dr["@middle_name"];
        result.LastName = (string) dr["@last_name"];
        result.ManagerID = (int) dr["@manager_id"];
        result.IsAdmin = (int) dr["@is_admin"];
        return result;
    }
}
0 голосов
/ 20 августа 2011

Что-то странное - я ожидаю, что ваш тест будет выглядеть так:

declare @succeedResult bit
declare @existErr bit
exec LogInUser @username=N'admin', @password =N'admin', @succeed = @succeedResult, @not_exist_err = @existErr

Но это приводит к простому ответу .... Вы вызываете свою функцию с допустимым (то есть существует) для имени пользователя и пароля?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...