Retrieve data from sql server compact 4.0 to textbox - c#

I have two text boxes in my winform. I would like to enter a userId into first text box, after that by clicking a button display a User Name in the second text box properly. The data is stored in sql server compact. Table name is Users, and this table contains two columns UserID and UserName.
With this code I can open a connection and retrieve the first value from the UserName column,
SqlCeConnection cn = new SqlCeConnection(#"Data Source = D:\Database\Training.sdf");
try
{
cn.Open();
SqlCeCommand cmd = new SqlCeCommand("SELECT UserID, UserName from Users;", cn);
TrainerNameBox.Text = cmd.ExecuteScalar().ToString();
cn.Close();
}
catch
{
}

ExecuteScalar returns first column of the first row. Other columns or rows are ignored.
In your case, your first column is UserID. That's why you get first value of this column.
If you want to get UserName value, you might need to change your query like;
SELECT UserName from Users
And looks like you forget to use WHERE clause in your query since you want to get UserName from UserID. You might need to use using statement to dispose your SqlCeConnection and SqlCeCommand.
Full example;
using(SqlCeConnection cn = new SqlCeConnection(#"Data Source = D:\Database\Training.sdf"))
using(SqlCeCommand cmd = cn.CreateCommand())
{
cmd.CommandText = "SELECT UserName from Users WHERE UserID = #id";
cmd.Parameters.AddWithValue("#id", (int)txtUserID.Text);
cn.Open();
TrainerNameBox.Text = cmd.ExecuteScalar().ToString();
}

You are missing the WHERE clause to isolate the username that you want to display
int userID;
if(!Int32.TryParse(txtUserID.Text, out userID))
{
MessageBox.Show("Invalid User ID number");
return;
}
using(SqlCeConnection cn = new SqlCeConnection(#"Data Source = D:\Database\Training.sdf"))
using(SqlCeCommand cmd = new SqlCeCommand("SELECT UserName from Users WHERE UserID=#id;", cn))
{
cn.Open();
cmd.Parameters.AddWithValue("#id", userID);
object result = cmd.ExecuteScalar();
if(result != null)
TrainerNameBox.Text = result.ToString();
else
MessageBox.Show("No user for ID=" + userID.ToString());
}
Notice that ExecuteScalar returns the first column of the first row, so you need to remove the UserID field from your query and if, the user is not found, you need to check for a null return.
Applying directly the ToString() method to your ExecuteScalar could raise an exception if your user types an invalid id. There is also the problem to validate the user input. If you type a not numeric value for the user id, the conversion will fail. In this case you need to check the input using Int32.TryParse

Try this:
Dataset ds = cmd.ExecuteDataset().ToString();
TrainerNameBox.Text = ds.tables[0].Rows[0][1].toString();
TrainerIDBox.Text = ds.tables[0].Rows[0][0].toString();

Related

Get data from SQL table to empty variable

I'm trying to search in table(called Accounts) for Username and in the line of this user in coulmn 4 that called PhotoId there is string that i need to get and add it to empty string value that i made before. thats what i tryied
i want to do it by Query like my code
string ecid = e.CallbackQuery.Message.Chat.Id.ToString();
using (SqlCommand sqlCommand = new SqlCommand("SELECT * from Accounts where Username like #username", con))
{
con.Open();
sqlCommand.Parameters.AddWithValue("#username", ecid);
string variable;
string userfound = (string)sqlCommand.ExecuteScalar();
con.Close();
if (userfound == ecid)
{
using (SqlCommand GotPhoto = new SqlCommand("SELECT PhotoId from Accounts where Username like #user", con))
{
con.Open();
GotPhoto.Parameters.AddWithValue("#user", ecid);
DataPid = GotPhoto.ExecuteScalarAsync().ToString();
con.Close();
// await bot.SendPhotoAsync("xxx", DataPid, capo, parseMode: ParseMode.Markdown, replyMarkup: zz);
await bot.SendTextMessageAsync(cid, "its been Poster", parseMode: ParseMode.Html);
}
}
else
{
MessageBox.Show("Not Working");
}
}
You are combining a SELECT * ... with ExecuteScalar(), which "returns the value of the first column in the first row of the resultset. Additional rows and columns are ignored."(https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executescalar(v=vs.110).aspx). Probably username is not the first column in the accounts table, so the content of another column is retured and your comparison fails.
Use SELECT username from Accounts where Username like #username instead.
EDIT
Depending on your data-model you can also combine the two queries into one as you are querying the same row twice.
con.Open();
using (var cmd = new SqlCommand("SELECT PhotoId from Accounts where Username like #user", con)) {
cmd.Parameters.AddWithValue("#user", ecid);
using (var reader = await cmd.ExecuteReaderAsync()) {
if (!reader.HasRows || ! reader.Read()) {
MessageBox.Show("User not found");
} else {
DataPid = cmd.GetYOURDATATYPE(0).ToString();
//....
}
}
}
con.Close();
According to the documentation of ExecuteScalar =>
Executes the query, and returns the first column of the first row in the result set returned by the query. Additional columns or rows are ignored.
When you perform string userfound = (string)sqlCommand.ExecuteScalar();
You are comparing the username to a value ( but wich one ? the value of the first column in the create table instruction)
I Suggest you change the first query to be sure to select username
PS:
To be consistant, you can also rename both of your query parameter #username instead of #user and #username because it refers exactly to the same thing.
You can perform only one query instead of two. ( select photoid ... where username = .. , and just check if the result contains one row )

IndexOutOfRange Exception in sqldatareader using c#

I create an application using c# , In my authentification interface , i have a test control , i want to know profile user .
My database contains table named user which contains 4 columns
(id_user,name ,mail, profile)
Here is my code
public string profil_user(string login)
{
SqlConnection conn = new database().connect_user();
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "select profile from user where name = '" + login + "';";
SqlDataReader s = cmd.ExecuteReader();
if (s.Read())
{
return ( s.GetString(3));
}
else{return ("false"); }
}
but i have an exception in s.GetString(3)
system.IndexOutOfRange : index was outside the bounds of the array
You're only selecting a single field (profile) but then you're trying to select the 4th field (index 3) here:
return ( s.GetString(3));
In addition to just returning s.GetString(0) I would strongly advise you to:
Use parameterized SQL - always do this, to prevent SQL injection attacks, make your code more readable, and prevent unexpected text conversion problems
Either throw an exception or return null if the profile isn't found, instead of returning the string "false"
Use using statements for disposable things like SqlCommand, SqlConnection and SqlDataReader to ensure that you clean up resources appropriately
Start following .NET naming conventions to make your code more idiomatic
So something like:
public string GetUserProfile(string login)
{
string sql = select profile from user where name = #login";
// I assume Connect() returns an *open* connection?
using (var conn = new Database().Connect())
{
using (var command = new SqlCommand(sql, conn))
{
command.Parameters.Add("#login", SqlDbType.NVarChar).Value = login;
using (var reader = command.ExecuteReader())
{
// If it's an error (code failure) for there to be no matching profile,
// you may want to throw an exception instead.
return s.Read() ? s.GetString(0) : null;
}
}
}
}
So you want the fourth row, not the fourth column which you try to access with s.GetString(3):
int rowNum = 0;
while(s.Read())
{
if(++rowNum == 4)
{
return s.GetString(0);
}
}
return "false";
However, it is a bit strange to access the fourth row when you don't use an Order By. You should also only return the row that you want with the correct sql query.
You are also open for sql injection if you use string concatenation here:
cmd.CommandText = "select profile from user where name = '" + login + "';";
Use sql parameters:
cmd.CommandText = "select profile from user where name = #login";
cmd.Parameters.Add("#login", SqlDbType.VarChar).Value = login;
have 4 columns not rows
Ok, so you instead want the fourth column. Why don't you use the name instead?
Since you only select the profile-column(the fourth), you could simply use GetString(0). But you could also select all columns and then determine the correct index with GetOrdinal:
int profileColumnIndex = s.GetOrdinal("profile");
return s.GetString(profileColumnIndex);
This is useful if you don't control the query or it might be changed in future.
You are selecting only 1 field, thus index 3 is out of bounds. It also very important to Use parameters. Try:
cmd.CommandText = "select profile from user where name = #login;";
cmd.Parameters.Add("#login, SqlDbType.NVarChar).Value = login;
SqlDataReader s = cmd.ExecuteReader();
while (s.Read())
{
return s[0].ToString();
}
The parameter for SqlDataReader.GetString should be the column index. You're only selecting one column so you get an exception.
Because you do not have all the fields in your select list
Change the SQL to:
select id_user,name ,mail, profile from user where name = '" + login + "';

C# - Select query not working in SqlCommand

I have to select user name from a database in SQL Server. The query that is generated by SqlCommand works in SQL Server Management Studio but not in my code.
And this only happens when the input is like AFFAQPC/affaq containing /.
The code is:
public int? getid()
{
SqlConnection Db = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString);
Db.Open();
// Searching for id in Users table from the logged in username
SqlCommand command = new SqlCommand("SELECT TOP 1 id FROM UsersLogin where username = '#user1';", Db);
command.Parameters.AddWithValue("#user1", userName);
string query = command.CommandText;
foreach (SqlParameter p in command.Parameters)
{
query = query.Replace(p.ParameterName, p.Value.ToString());
}
Trace.WriteLine(query);
using (SqlDataReader reader = command.ExecuteReader())
{
if (reader.Read())
{
Trace.WriteLine("111");
int id = Convert.ToInt32(reader["id"]);
Trace.WriteLine(id);
Db.Close();
return id;
}
}
Db.Close();
return null;
}
The error occurs when input contains a /.
The query that is generated in SqlCommand:
SELECT TOP 1 id
FROM UsersLogin
WHERE username = 'AFFAQPC\affaq';
remove the single quotes from your query string
username = '#user1'
to
username = #user1
The "Parameter" should be WITHOUT the "#", just the name
command.Parameters.AddWithValue("user1", userName);
if the userName value is a string (confirming whatever your source is), that will be properly recognized when processed. You do not need to explicitly quote-it. Otherwise, the query is specifically looking for a user '#user1' which is probably why it is not returning what you expect.
I have NO idea why you are cycling through all parameters to assign the value... the userName field should already be good to go without doing your foreach parameter check.

winform login check from database

I made a login form for an application, and I want to check if the login data from the user exists in the database so that he can log in successfully or display an message telling him that his login details are wrong.
I tried the OleDbDataReader but that didn't work, so I added a username and password in my database (in the table Etudiant) and tried to count the number of rows in the table Etudiant, so that the login succeeds if the count is greater than 0, otherwise "wrong details" is shown. But the problem is always the same, only the second message is shown.
Here's my code:
string strcnn = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=app.mdb";
OleDbConnection cnn = new OleDbConnection(strcnn);
cnn.Open();
string reqet = "SELECT count(*) FROM Etudiant";
OleDbCommand cmd = new OleDbCommand(reqet, cnn);
int x = (int)cmd.ExecuteScalar();
if (x>0)
MessageBox.Show("Bienvenu cher étudiant");
else
MessageBox.Show("Données invalides !");
cnn.Close();
You must check the username and password on your query or it will return the full table row count, someting like SELECT COUNT(*) FROM Etudiant WHERE User=(username) AND Password=(password).

Getting Exception When Invoking The Subroutine ExecuteReader

I have SQL Server Compact 3.5 database that contains account information. But everytime I call the function ExecuteReader I get this exception below:
The column name is not valid. [ Node
name (if any) = ,Column name = ID ]
But that is the correct column name. The column names are the following: Username, Password, Date Created, and etc.
Here is the code below:
SqlCeConnection connection = new SqlCeConnection(#"Data Source=C:\Users\Danny\Documents\Visual Studio 2010\Projects\Databinding Login Form\Databinding Login Form\MyDatabase#1.sdf; Password=*********");
connection.Open();
SqlCeCommand com = new SqlCeCommand("SELECT * FROM Accounts WHERE ID=Username", connection);
SqlCeDataReader reader = com.ExecuteReader();
if (username.Text == reader["Username"] as string && password.Text == reader["Password"] as string)
{
MessageBox.Show("Login Successfull!", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show("Access Denied 5", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
Do you have a column called "ID"?
It looks like you are asking for all accounts which have the same value in "Username" and "ID" columns? Did you meant to substitute "ID" for something?
Example
Where Username = 'EnteredUsername'
Looks like your query "SELECT * FROM Accounts WHERE ID=Username" may be the problem. As you mentioned Username is a column-name; looks like you should be putting the user id in the query i.e "dlopez" for instance: "SELECT * FROM Accounts WHERE ID='dlopez'"
The where clause is cause the error. I assume you want to select only one Account where the ID is equal to a local variable caller username. One solution is:
SqlCeCommand com = new SqlCeCommand("SELECT * FROM Accounts WHERE ID='"
+ username + "'", connection);
A more correct solution is to use a SqlCeParameter:
SqlCeCommand com = new SqlCeCommand("SELECT * FROM Accounts WHERE ID=#UserName", connection);
SqlCeParameter param = new SqlCeParameter("#UserName", SqlDbType.NVarChar);
param.Value = username;
com.Parameters.Add(param);

Categories