0

I'm trying to fetch a record from the database using a stored procedure, but it returns null in SqlDataReader object.

Here is my code:

public Buybest_Liberary.Data.UserManagement getUser(string email)
{
    Buybest_Liberary.Data.UserManagement obj = new Buybest_Liberary.Data.UserManagement();
    string conString = @"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\ahmadshair\Documents\Buybest.mdf;Integrated Security=True;Connect Timeout=30";

    SqlConnection connection = new SqlConnection(conString);
    connection.Open();

    SqlCommand _cmd = new SqlCommand("getUserRecord", connection);
    _cmd.CommandType = CommandType.StoredProcedure;
    _cmd.Parameters.Add("@Email", SqlDbType.NVarChar).Value = email;

    SqlDataReader dr = _cmd.ExecuteReader();

    if (dr.HasRows)
    {
        obj.UId = Convert.ToInt32(dr[0]);
        obj.Email = dr[1].ToString();
        obj.Password = dr[2].ToString();
    }

    return obj;
} 
1
  • What is the definition of getUserRecord? Are you really sure it returns some data? Commented Nov 27, 2015 at 11:45

3 Answers 3

5

You need to call dr.Read() before accessing the data! Also: put your disposable objects (SqlConnection, SqlCommand, SqlDataReader) into using(..) { ... } blocks to ensure proper disposal:

public Buybest_Liberary.Data.UserManagement getUser(string email)
{
    Buybest_Liberary.Data.UserManagement obj = new Buybest_Liberary.Data.UserManagement();

    // You should read the connection string from a config file 
    // don't specify it explicitly in code!
    string conString = ConfigurationManager.ConnectionStrings["-your-connection-string-name-here-"].ConnectionString;

    using (SqlConnection connection = new SqlConnection(conString))
    using (SqlCommand _cmd = new SqlCommand("getUserRecord", connection))
    {
        _cmd.CommandType = CommandType.StoredProcedure;
        _cmd.Parameters.Add("@Email", SqlDbType.NVarChar).Value = email;

        connection.Open();

        using (SqlDataReader dr = _cmd.ExecuteReader())
        { 
            // the SqlDataReader could return *multiple* rows - how are you
            // going to deal with that? Create an object for each row of data
            // and add them to a list to return? 
            while (dr.Read())
            {
                 obj.UId = Convert.ToInt32(dr[0]);
                 obj.Email = dr[1].ToString();
                 obj.Password = dr[2].ToString();
            }

            dr.Close();
        }

        connection.Close();
    }

    return obj;
} 

Also: what do you do if your stored procedure returns multiple rows of data? You need to somehow deal with that, too

Sign up to request clarification or add additional context in comments.

4 Comments

Also, don't hard code the connection string. read it from config file. No need to call dr.Close() nor connection.Close() because dr and connection are enclosed in using blocks
@JesúsLópez: agreed - the connection string was copied from the question - not my doing. And yes - there's no strict need to call dr.Close() or connection.Close() - but doing so doesn't hurt, either - I prefer to be explicit.
that's fine. However I think it's better to teach best practices to newcomers rather than simply answer directly the question.
Thanks, It is helpful.
4

If I am not mistaken you are missing a dr.Read() to fetch the first record.

Comments

2

HasRows is simply telling you whether or not there are any rows to read, whereas Read() advances the internal cursor to the next row in the data, and incidentally returns False if there are no more rows to read, or True if there was another row available. We need dr.read()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.