Selecting and retrieving multiple cells in different rows - c#

I'm trying to retrieve multiple cells in different rows where the correct owner exists, but I'm only being able to retrieve the first match and it stops there, I've tried using it with a for, but I don't think .ExecuteScalar() is the way to do this. Maybe I'm just stupid and doing it completely wrong.
Code:
checkPlayerName = API.getPlayerName(player);
string checkOwnedCars = "SELECT COUNT(*) FROM [carOwners] WHERE Owner='" + checkPlayerName + "'";
con.Open();
SqlCommand checkCarsCount = new SqlCommand(checkOwnedCars, con);
int carsCountToVar = Convert.ToInt32(checkCarsCount.ExecuteScalar());
con.Close();
for (int i = 0; i < carsCountToVar; i++)
{
string displayCars = "SELECT LP FROM [carOwners] WHERE Owner='" + checkPlayerName + "'";
con.Open();
SqlCommand displayCarsCMD = new SqlCommand(displayCars, con);
string displayCarsToVar = displayCarsCMD.ExecuteReader().ToString();
API.sendChatMessageToPlayer(player, "Owned Vehicle: " + displayCarsToVar.ToString());
con.Close();
}
Table
For example, LP on 2nd and 3rd row are the ones that I want to store since both belong to the same owner, yet only first cell data (1337) is displaying.

You are not iterating the results you are getting from query.
Plus always use Parameterized queries to prevent SQL Injection Attacks
SqlCommand command = new SqlCommand("SELECT LP FROM [carOwners] WHERE Owner=#checkPlayerName", con);
command.Parameters.AddWithValue("#checkPlayerName",checkPlayerName);
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine(String.Format("{0}",reader["id"]));
//API.sendChatMessageToPlayer(player, "Owned Vehicle: " + reader["id"].ToString());
}
}
conn.Close();

Related

MySqlDataReader Hasn't Row But Query has data

My Query in PHPmyadmin has result but in C#, a.read() returns no data.
string query = "SELECT answer FROM tbl WHERE level = " + level + " AND subject = '" + subject[i] + "';";
MySqlCommand command = new MySqlCommand(query, connection);
connection.Open();
MySqlDataReader a = command.ExecuteReader();
while (a.Read())
{
//Do Some Things
}
connection.Close();
Edit:
I've already tried parameterized queries, didn't work, and also tried with the constant values from the table, it doesn't work in the project, but when I run the query in the database it works

how to display count in label text?

i am having a hard time to display my count code to my label text. here is my code and please tell me how to solve this problem.
ordering_and_billing.dBase dBase = new ordering_and_billing.dBase();
var mydbconnection = new dBase.dbconnection();
string sql = "SELECT * FROM `order` WHERE eventdate='" + lbldte.Text + "'";
MySqlCommand cmd = new MySqlCommand(sql, mydbconnection.Connection);
mydbconnection.Connection.Open();
MySqlDataReader rdr = cmd.ExecuteReader();
if (rdr.HasRows)
{
while (rdr.Read())
{
Int32 count = (Int32)cmd.ExecuteScalar();
string disp = count.ToString();
lblcount.Text = disp;
}
}
just use count function:
string sql = "SELECT COUNT(*) FROM `order` WHERE eventdate='" + lbldte.Text + "'";
also don't use ExecuteReader, use ExecuteScalar function if you want a single value like a count value:
lblcount.Text =cmd.ExecuteScalar().toString();
You should use SELECT COUNT(*) if all you want is the record count.
string sql = "SELECT COUNT(*) FROM `order` WHERE eventdate='" + lbldte.Text + "'";
However, keep in mind that rdr.Read() reads a new row from the sql query. Every time you get a new row, you're trying to rerun the sql command (which I'm guessing crashes) and then assign the count label. So you're trying to assign the count label count times. Use this construct instead:
int count = 0;
while (rdr.Read())
{
count++;
}
lblcount.Text = count.ToString(); //only assigns to the Text property once
never mind guys i got my answer now.
ordering_and_billing.dBase dBase = new ordering_and_billing.dBase();
var mydbconnection = new dBase.dbconnection();
string sql = "SELECT * FROM `order` WHERE eventdate='" + lbldte.Text + "'";
MySqlCommand cmd = new MySqlCommand(sql, mydbconnection.Connection);
mydbconnection.Connection.Open();
MySqlDataReader rdr = cmd.ExecuteReader();
int count = 0;
while (rdr.Read())
{
count ++;
}
lblcount.Text = count.ToString();

loop through all values in sql table using sql data reader

I want to fetch all rows that related to the query below, my problem that only one row retrived not all rows , iam using asp.net with c# and ado.net and my code logic is
if (!IsPostBack)
{
string username = Session["username"].ToString();
con.Open();
string strqryScript = "select * from dbo.teachers where user_id = '" + username + "'";
SqlCommand cmd = new SqlCommand(strqryScript, con);
SqlDataAdapter da = new SqlDataAdapter(cmd);
SqlDataReader rdr = cmd.ExecuteReader();
rdr.Read();
string name = rdr["teach_id"].ToString();
rdr.Close();
string query = "select * from dbo.teacher_classes where teach_id = '" + name + "' ORDER BY class_id";
SqlCommand cmd2 = new SqlCommand(query, con);
SqlDataAdapter da2 = new SqlDataAdapter(cmd2);
SqlDataReader rdr2 = cmd2.ExecuteReader();
while (rdr2.Read())
{
classname.Text = rdr2["class_id"].ToString();
}
con.Close();
}
extra note that i can use gridview to bind data but i want to fill my table with custom information from many tables , so i want to use an html table and fill it with my custom data. any help please! and thanks ..
While looping on the second reader, you write the value extracted from the reader on the Text property of the classname label. This will overwrite the previous text and leave you with the name of the last teacher retrieved. You need to add to the previous text or use a List.
classname.Text += rdr2["class_id"].ToString();
Said that, let me point you to a big problem in your code. String concatenation is really bad when you build sql commands. It gives you back syntax errors (if your input text contains single quotes) or Sql Injection as explained here
You should use parameterized queries like this (just for your first command)
string strqryScript = "select * from dbo.teachers where user_id = #id";
SqlCommand cmd = new SqlCommand(strqryScript, con);
cmd.Parameters.AddWitValue("#id", username);
....
This is the issue you need to fix:
classname.Text = rdr2["class_id"].ToString(); <== always setting the same text!!
You need to make sure, you fill a list, a dataset or whatever, when reading the data!

Problem in populating the GridView in ASP.NET(C#)

I'm trying to populate a Gridview with results from loop. But I'm getting only last result in the loop.
I think GridView is being overwritten on every time the for loop is being executed.
Can you people help me to remove this problem please.
for (int j = 0; j < i; j++)
{
Label1.Text += fipath[j];
Label1.Text += "-------------";
SqlConnection conn = new SqlConnection("Server=ILLUMINATI;" + "Database=DB;Integrated Security= true");
SqlCommand comm = new SqlCommand("Select * from FileUpload where UploadedBy='" + NAME + "' AND FilePath='" + fipath[j] + "'", conn);
try
{
conn.Open();
SqlDataReader rdr = comm.ExecuteReader();
if (Role.Equals("admin"))
{
GridView1.DataSource = rdr;
GridView1.DataBind();
}
rdr.Close();
}
catch
{
conn.Close();
}
}
There is more than one problem with this code:
seems like if Role== "admin" you don't need to query db at all
DataSource of the grid is overridden on every loop iteration, this is why you see only the last value.
use parameters for SqlCommand to prevent SQL injection.
don't run string concatenation in the loop. Use StringBuilder instead
use using for your connection. The code is cleaner this way.
The fix could look like this:
if (Role != "admin")
return;
var dataTable = new DataTable();
var stringBuilder = new StringBuilder();
using (var connection = new SqlConnection("Server=ILLUMINATI;" + "Database=DB;Integrated Security= true"))
using (var command = connection.CreateCommand())
{
connection.Open();
command.CommandText = "Select * from FileUpload where UploadedBy = #UploadedBy AND FilePath = #FilePath";
command.Parameters.AddWithValue("UploadedBy", NAME);
var filPathParameter = command.Parameters.Add("FilePath", SqlDbType.VarChar);
for (int j = 0; j < i; j++)
{
stringBuilder.Append(fipath[j]);
stringBuilder.Append("-------------");
filPathParameter.Value = fipath[j];
dataTable.Load(command.ExecuteReader(), LoadOption.PreserveChanges);
}
}
Label1.Text += stringBuilder.ToString();
GridView1.DataSource = dataTable;
GridView1.DataBind();
Also, I don't know how many elements your normal loop is. If it is one or two and you have appropriate indexes in FileUpload table then it is ok to leave as is. However, if you need to do the for many times you should consider switching to a single query instead
For example:
var filePathes = string.Join(",", fipath.Select(arg => "'" + arg + "'"));
var command = "Select * from FileUpload where UploadedBy = #UploadedBy AND FilePath in (" + filePathes + ")";
This query is SQL injection prone. And has a 2100 elements limit in MS SQL.
There is more than one way to approach this. Depends on your DBMS and requirements.
Use the in clause in SQL Query and pass the list of ID's in FilePath
SqlCommand comm = new SqlCommand("Select * from FileUpload where UploadedBy='" + NAME
+ "' AND FilePath in (" + listOfIDs + ")", conn);
Check out these URLs that are related to the use of in clause.
Techniques for In-Clause and SQL Server
Parameterizing a SQL IN clause?
Create a list or BindingSource outside the loop, bind that to your gridview and then add all records to that list or source.
The problem with your current approach is that you are overwriting the records pulled from the database with a new datasource each time, so as you stated, only the last one is "set", and the older assignments are disposed of.

Need help with database connection and query code

In my code below, the cmdquery works but the hrquery does not. How do I get another query to populate a grid view? Do I need to establish a new connection or use the same connection? Can you guys help me? I'm new to C# and asp. Here's some spaghetti code I put together. It may all be wrong so if you have a better way of doing this feel free to share.
if (Badge != String.Empty)
{
string cmdquery = "SELECT * from Employees WHERE Badge ='" + Badge + "'";
string hrquery = "SELECT CLOCK_IN_TIME, CLOCK_OUT_TIME FROM CLOCK_HISTORY WHERE Badge ='" + Badge + "'";
OracleCommand cmd = new OracleCommand(cmdquery);
cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
conn.Open();
OracleDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
this.xUserNameLabel.Text += reader["EMPLOYEE_NAME"];
this.xDepartmentLabel.Text += reader["REPORT_DEPARTMENT"];
}
OracleCommand Hr = new OracleCommand(hrquery);
Hr.Connection = conn;
Hr.CommandType = CommandType.Text;
OracleDataReader read = Hr.ExecuteReader();
while (read.Read())
{
xHoursGridView.DataSource = hrquery;
xHoursGridView.DataBind();
}
}
conn.Close();
Your data access code should generally look like this:
string sql = "SELECT * FROM Employee e INNER JOIN Clock_History c ON c.Badge = e.Badge WHERE e.Badge = #BadgeID";
using (var cn = new OracleConnection("your connection string here"))
using (var cmd = new OracleCommand(sql, cn))
{
cmd.Parameters.Add("#BadgeID", OracleDbType.Int).Value = Badge;
cn.Open();
xHoursGridView.DataSource = cmd.ExecuteReader();
xHoursGridView.DataBind();
}
Note that this is just the general template. You'll want to tweak it some for your exact needs. The important things to take from this are the using blocks to properly create and dispose your connection object and the parameter to protect against sql injection.
As for the connection question, there are exceptions but you can typically only use a connection for one active result set at a time. So you could reuse your same conn object from your original code, but only after you've completely finished with it from the previous command. It is also okay to open up two connections if you need them. The best option, though, is to combine related queries into single sql statement when possible.
I'm not even going to get into how you should be using usings and methods :p
if (Badge != String.Empty)
{
string cmdquery = "SELECT * from Employees WHERE Badge ='" + Badge + "'";
string hrquery = "SELECT CLOCK_IN_TIME, CLOCK_OUT_TIME FROM CLOCK_HISTORY WHERE Badge ='" + Badge + "'";
OracleCommand cmd = new OracleCommand(cmdquery);
cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
conn.Open();
OracleDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
this.xUserNameLabel.Text += reader["EMPLOYEE_NAME"];
this.xDepartmentLabel.Text += reader["REPORT_DEPARTMENT"];
}
OracleCommand Hr = new OracleCommand(hrquery);
Hr.Connection = conn;
Hr.CommandType = CommandType.Text;
OracleDataReader read = Hr.ExecuteReader();
//What's this next line? Setting the datasource automatically
// moves through the data.
//while (read.Read())
//{
//I changed this to "read", which is the
//datareader you just created.
xHoursGridView.DataSource = read;
xHoursGridView.DataBind();
//}
}
conn.Close();

Categories