8

Here is my GeneralFunctions:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;

/// <summary>
/// Summary description for GeneralFunctions
/// </summary>
public class GeneralFunctions
{
    public GeneralFunctions ()
    {
        //
        // TODO: Add constructor logic here
        //
    }

    public static DataTable GetData ( string query )
    {
        SqlDataAdapter dataAdapter;
        DataTable table;

        try
        {
            dataAdapter = new SqlDataAdapter( query, GetConnectionString() );
            table = new DataTable();

            dataAdapter.Fill( table );
            return table;
        }
        catch ( Exception ex )
        {
        }
        finally
        {
            dataAdapter = null;
            table = null;
        }

        return table;
    }

    private static string GetConnectionString ()
    {
        string connectionString = ConfigurationManager.ConnectionStrings[ "CAPortalConnectionString" ].ConnectionString;

        return connectionString;
    }

    public static int? AuthenticateLogin ( string username, string password )
    {
        using ( var conn = new SqlConnection( GetConnectionString() ) )
        using ( var cmd = conn.CreateCommand() )
        {
            conn.Open();
            cmd.CommandText =
            @"SELECT 
                 DistID 
             FROM 
                 Distributor
             WHERE 
                 Username = @username 
             AND 
                 Password = @password";
            cmd.Parameters.AddWithValue( "@username", username );
            cmd.Parameters.AddWithValue( "@password", password );
            using ( var reader = cmd.ExecuteReader() )
            {
                if ( !reader.Read() )
                {
                    // no results found
                    return null;
                }
                return reader.GetInt32( reader.GetOrdinal( "DistID" ) );
            }
        }
    }

    public static string GetDistInfo ( int distID )
    {
        using ( var conn = new SqlConnection( GetConnectionString() ) )
        using ( var cmd = conn.CreateCommand() )
        {
            conn.Open();
            cmd.CommandText =
            @"SELECT 
                 FName + ' ' + LName AS Name
             FROM 
                 Distributor
             WHERE 
                 DistID = @distid";
            cmd.Parameters.AddWithValue( "@distid", distID );
            using ( var reader = cmd.ExecuteReader() )
            {
                return reader.GetString( reader.GetOrdinal( "Name" ) );
            }
        }
    }

}

Here is my login page:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class index : System.Web.UI.Page
{
    protected void Page_Load ( object sender, EventArgs e )
    {

    }
    protected void but_login_Click ( object sender, EventArgs e )
    {
        if ( username_id.Text != "" || password.Text != "" )
        {
            // Verify the username and password match the database
            var distId = GeneralFunctions.AuthenticateLogin( username_id.Text, password.Text );

            if ( distId != null )
            {
                // User is authenticated
                var name = GeneralFunctions.GetDistInfo( (int)distId );
                Session[ "DistName" ] = name;
                Session[ "DistID" ] = distId;

                Response.Redirect( "dashboard.aspx", false );
            }
            else
            {
                // provide error label here username and password do not match
                authentFailed.Text = "Username / Password did not match our records";
            }
        }
        else
        {
            // Username or Password blank error lable
            authentFailed.Text = "Please Input Username / Password";
        }
    }
}

Before I added the GetDistInfo method it worked just fine, logged in the user. I then tried to add Session variables and the GetDistInfo method. I pass in the DistID returned from AuthenticateLogin into the GetDistInfo method. It errors out with the following error:

Exception Details: System.InvalidOperationException: Invalid attempt to read when no data is present.

Source Error:

Line 95:             using ( var reader = cmd.ExecuteReader() )
Line 96:             {
Line 97:                 return reader.GetString( reader.GetOrdinal( "Name" ) );
Line 98:             }
Line 99:         }


Source File: c:\inetpub\wwwroot\Base\ClientAccessPortal\App_Code\GeneralFunctions.cs    Line: 97 

When I run the SQL against the database it correct pulls back the clients name. I'm not sure why it isn't doing that inside the code. Anyone able to see what I am missing?

Josh Darnell
  • 11,304
  • 9
  • 38
  • 66
James Wilson
  • 5,074
  • 16
  • 63
  • 122

2 Answers2

22

Please try replacing this. Actually Read() was missing in your code.

using ( var reader = cmd.ExecuteReader() )
{
     return reader.GetString( reader.GetOrdinal( "Name" ) );
}

With following

using ( var reader = cmd.ExecuteReader() )
{
     if(reader.Read())
     {
          return reader.GetString( reader.GetOrdinal( "Name" ) );
     }
     return null;
}
Pankaj
  • 9,749
  • 32
  • 139
  • 283
  • I added the return null and this fixed it. Can you help me understand why this was looking for a null when the read will always return a result? – James Wilson Apr 13 '12 at 18:50
  • The compiler is noticing that there is no return statement. The compiler cannot prove that the code path will never leave and so it is expecting to hit a return statement. – Pankaj Apr 13 '12 at 18:57
  • you were the first to post the return null solution and it worked like a charm. Must check this as the answer. Thank you all for your help and quick responses. – James Wilson Apr 13 '12 at 19:10
4

You need to read first (you're doing it when using the reader above in your code):

using ( var reader = cmd.ExecuteReader() )
{
    // you haven't positioned yourself on a record yet.
    while (reader.Read())
    {
        return reader.GetString( reader.GetOrdinal( "Name" ) );
    }
    return string.Empty;
}

EDIT To respond to the error you got; since you define your function

public static string GetDistInfo ( int distID )

all possible ways "out of the function" must return something. In your case you should return a string or maybe null depending on what you want to do.

Asken
  • 7,679
  • 10
  • 45
  • 77
  • This seemed to be a step in the right direction but it is giving me a new error now: Compiler `Error Message: CS0161: 'GeneralFunctions.GetDistInfo(int)': not all code paths return a value` Anyideas on that? – James Wilson Apr 13 '12 at 18:43
  • `String.Empty` will take memory like a chocolate. – Pankaj Apr 13 '12 at 18:54
  • Microptimization... @James, use what is appropriate to suite you needs. – Asken Apr 13 '12 at 18:56
  • 1
    @PankajGarg, read this http://stackoverflow.com/questions/6689876/string-empty-vs-null-which-one-do-you-use – Asken Apr 13 '12 at 18:57
  • I was having the memory issue in past. Finally I got to know I should not use `String.Empty` comparing it with `null` Because `null` does not cost you anything. Verified it with `Red Gate Ants Memory Profiler`. – Pankaj Apr 13 '12 at 19:01
  • 1
    I'd suggest you check the rest of your code rather than a static which is defined once... what you are saying doesn't make sense. – Asken Apr 13 '12 at 19:03
  • Small problems make big issues and they are very simple/easy to ignore. – Pankaj Apr 13 '12 at 19:08