3

I am a high school student who's still pretty much a beginner in C#.

I am making a library management system (for books) that includes a database (sql local database in visual studio(?)) for users. I have a form wherein users can view the data they have input in the registration form (userID, name, username, course, section). The only problem is that it only displays the data of the first account created. No matter how many other accounts I create, it still only ever displays the first one. How do I make it so that it shows the data of the "current" user/account logged in?

I've tried slightly changing the code by changing

SqlCommand cmd = conn.CreateCommand();
               cmd.CommandType = CommandType.Text;
               cmd.CommandText = "Select * from [tbl_accounts]";

into

string select = "Select * from [tbl_accounts]";
               SqlCommand cmd = new SqlCommand(select, conn);

Although, I think they're basically the same. I don't really know what to do since the other solutions I've found are much more complex.

This is the code that I am using right now:

try
{
   SqlConnection conn = new SqlConnection(@"[connection string]");
   conn.Open();

   string select = "Select * from [tbl_accounts]";
   SqlCommand cmd = new SqlCommand(select, conn);
   SqlDataReader dr = cmd.ExecuteReader();

   if(dr.Read())
   {
       materialLabel6.Text = dr["accountID"].ToString();
       materialLabel7.Text = dr["username"].ToString();
       materialLabel8.Text = dr["name"].ToString();
       materialLabel9.Text = dr["strand"].ToString();
       materialLabel10.Text = dr["section"].ToString();
   }

}
catch (Exception ex)
{ 
   MessageBox.Show(ex.Message);}      
}

The outcome that I would like to see is for example:

Users(table):

  1. PersonA
  2. PersonB

Currently Logged in: PersonB

[PERSONB'S DATA]

So it means that the form will only display the data of PersonB instead of PersonA's

Dortimer
  • 619
  • 8
  • 25
aii
  • 31
  • 3

1 Answers1

4

For starters, if you need more than one row of data, you'll want to loop through all the rows in the data reader. Right now you're only getting the first row returned. This link should have the relevant information for that. However, ideally, you'd want to send a parameter from the UI (or whatever it is that you're using to fire off the call to the function) that denotes the user (an ID or any unique field in the Users table) and send that to the sql query's where clause so you only pull the record(s) that you need.

The query should probably look something like:

public void GetUserInfo(int userId) // though you might want to change the parameter to suit your needs. It's hard to tell without being able to see the schema
{
    string select = string.Format("Select * from [tbl_accounts] where Id = {0}", userId.ToString()); // something along these lines
    SqlCommand cmd = new SqlCommand(select, conn);

    SqlDataReader dr = cmd.ExecuteReader();

    if(dr.Read())
    {         
        materialLabel6.Text = dr["accountID"].ToString();
        materialLabel7.Text = dr["username"].ToString();
        materialLabel8.Text = dr["name"].ToString();
        materialLabel9.Text = dr["strand"].ToString();
        materialLabel10.Text = dr["section"].ToString();
    }
}

Edit: quick note, if you adjust your query so it pulls one record based off of a parameter, you shouldn't need to do the looping.

Another quick edit: I broke up the code so it's a little more readable. This is more of an 'ideal implementation,' and enforces some better practices for code. (I know it's a high school project, but it's best to get used to breaking up code so it's more generic early on imo. This is mostly for maintainability. On larger projects keeping everything so closely coupled together is hard to manage.)

public User GetUserInfo(int userId) // though you might want to change the parameter to suit your needs. It's hard to tell without being able to see the schema for the user table
{

    SqlConnection conn = new SqlConnection(@"[connection string]");
    conn.Open();

    string select = string.Format("Select * from [tbl_accounts] where Id = {0}", userId.ToString()); // something along these lines
    SqlCommand cmd = new SqlCommand(select, conn);

    SqlDataReader dr = cmd.ExecuteReader();

    User user = new User();

    if(dr.Read())
    {   
        user.AccountId = dr["accountID"].ToString();
        user.UserName = dr["username"].ToString();
        user.Name = dr["name"].ToString();
        user.Strand = dr["strand"].ToString();
        user.Section = dr["section"].ToString();
    }
    return user;
}

public void SetValues(User user) 
{
    materialLabel6.Text = user.AccountId;
    materialLabel7.Text = user.UserName;
    materialLabel8.Text = user.Name;
    materialLabel9.Text = user.Strand;
    materialLabel10.Text = user.Section;
}


public class User 
{
    string AccountId { get; set; }
    string UserName { get; set; }
    string Name { get; set; }
    string Strand { get; set; }
    string Section { get; set; }
}
Dortimer
  • 619
  • 8
  • 25
  • 1
    May I ask what the public class is for? I'm sorry I'm not that familiar with other terms yet... and thank you! – aii May 07 '19 at 15:07
  • No worries. That's just a sample function that returns a potential class that you could make called `User`. Personally, I'd add that class and add members for all the columns in the User table, then populate a `User` object with the `DataReader` results, and then send the object back to the UI so the `MaterialLabel`s can be set by that object's values. – Dortimer May 07 '19 at 15:12
  • @Anonymousse I updated the answer and split the two examples so it should be a little more clear and easier to read. – Dortimer May 07 '19 at 15:55
  • 1
    @Dortimer dude, you gave name variable returnValue, but in Read() you filling user and return user. Could you fix it for more clearly code. – evilGenius May 07 '19 at 16:00
  • @evilGenius my mistake. I was typing it up pretty quick – Dortimer May 07 '19 at 16:02
  • 1
    @Dortimer it's ok) I just wanted improve your answer) – evilGenius May 07 '19 at 16:03
  • Are the string variables in the public class User "members"? What does the function "User" do? And also is there a site that could help me with the necessary/important jargon in programming? Thank you once more and I apologize for the increasing number of questions. – aii May 07 '19 at 16:10
  • 1
    The User class (`public class User`) should have strings or variables that match the data types (`string`, `int`, `double`, etc) in the SQL table you're referencing. The top block of code in the second example: `public User GetUserInfo(int userId)` is a method that takes a parameter for finding the user's data by the Id in the database and returns a User object. If the database doesn't have an 'Id` column, you'll want to change the parameter to find unique user data(sometimes methods are called a function, but 'method' is more common these days, and the terms more-or-less mean the same thing) – Dortimer May 07 '19 at 16:27
  • Also, ideally, the `public class User` code should go in its own file and the method `public User GetUserInfo(int userid)` should also be in a separate file. Essentially you want to break up the code so each file serves a distinct purpose (defining a class, having methods for doing database look up and saving, and in this case, setting elements on the UI). There's a ton of different sites that list the jargon, but it can be hard to internalize what they mean without reference code. I'd suggest googling "C# for beginners" and look for a tutorial. Good ones walk you through with code examples. – Dortimer May 07 '19 at 16:33
  • Not to sound derisive or anything. It sounds like they really threw you in the deep end with starting with data access so early. – Dortimer May 07 '19 at 16:41