How to print 2 columns retrieved from SQL Server database - c#

Something missing with the code (I guess). I want to show the student id and name in the list box. But I see this:
I can't figure out the problems especially with the inner join.
private void button1_Click(object sender, EventArgs e)
{
string strName = "";
connect.Open();
SqlCommand command = new SqlCommand(" Select Student_tbl.StudentName, Student_tbl.StudentID, Module_tbl.ModuleID FROM[Course-Student] INNER JOIN Student_tbl ON [Course-Student].SID = Student_tbl.StudentID INNER JOIN Module_tbl ON[Course-Student].CID = Module_tbl.ModuleID WHERE(Module_tbl.ModuleID = '" + tbCourse.Text+"')",connect);
command.ExecuteNonQuery();
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
strName = reader[1].ToString();
listBox1.Items.Add(strName);
}
connect.Close();
}

You are printing retrieving from the reader only the StudentID field. Change your while loop as follows to retrieve both fields and concatenate the values:
while (reader.Read())
{
var name = reader[0].ToString();
var id = reader[1].ToString();
listBox1.Items.Add(id + " " + name);
}
You can also use String Interpolation (which is C# 6 syntactic sugar for string.Format) like this:
while (reader.Read())
{
listBox1.Items.Add($"{reader[1].ToString()} {reader[0].ToString()}");
}
Also, as for the sql statement: Do not use string concatenation to create the statement. This is susceptible for SQL Injections. Use instead Parameterized Queries

Related

How to use SELECT + parameter + FROM in SQL database?

I want to know if it is possible to create a query like that:
SELECT :parameterA, :paramaterB
FROM *someTable*;
The idea is to use some structure like that instead of making some sort of string or something like that.
I´m working with SQL database and a C# project in Visual Studio 2019.
So far I have this code:
public List<V_Requerimientos> GetData(int idEmpresa, string columns)
{
List<V_Requerimientos> result = null;
try
{
var dyParam = new OracleDynamicParameters();
dyParam.Add("idEmpresa", OracleDbType.Int32, ParameterDirection.Input, value: idEmpresa);
var conn = this.GetConnection();
if (conn.State == ConnectionState.Closed)
{
conn.Open();
}
if (conn.State == ConnectionState.Open)
{
string query = "SELECT " + columns + "FROM V_REQUERIMIENTOS " +
"WHERE EMPR_CODIGO = :idEmpresa AND ETAR_CODIGO <> 4";
result= conn.Query<V_Requerimientos>(query, dyParam).ToList();
conn.Close();
}
}
catch (Exception e)
{
throw e;
}
return result;
}
where idEmpresa is the PK of the object selected in the front, and columns is a string which contains the columns I want to select for that object.
I was wondering if there is anyway for replace columns for parameters sent to the method instead of using the concatenated query as I have at the moment.
SQL parameters are used to specify value in the where clause. You would not use parameters for column names. Your query should look more like this.
string colA = "Customer Id";
string colB = "Customer Name";
string sql = $"Select [{colA}], [{colB}] from table";

make many mysql command in one connection in c# visual studio & unknown column in where clause

I have mySql database contains ID, projectName, companyName, projectNum, .. etc
I need to create Combobox that display projectName (project name isn't unique)
when I try to execute this the following error appears:
"Unknown column 'proj2' in where clause"
even though when I try to print this value it prints successfully in my code.
so I changed to display ID in Combobox and works well
now I need if I choose one ID to fill some fields (projectName, companyName, projectNum) then display values in other Combobox (e.g Combobox2) it has item number which is not unique and it
depend on projectName field.
I try to make one connection and two connection but both of them didn't work.
nothing appears in Combobox2
when I try to choose ID from first Combobox the same error appears:
"Unknown column 'proj2' in where clause"
I don't know if should I change the design of the database.
again I should mention that project name, company name, project number may be repeated in more than 50 records.
below is the code
first function to fill the first Combobox:
private void Form2_Load(object sender, EventArgs e)
{
try
{
// String getQuery = "Select projectName From ubc.BOQ_Table Group By projectName";
String getQuery = "Select ID From ubc.BOQ_Table";
connection.Open();
MySqlCommand command = new MySqlCommand(getQuery, connection);
MySqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
for (int i = 0; i < reader.FieldCount; i++)
{
comboBox1.Items.Add(reader.GetString("ID"));
}
}
reader.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
connection.Close();
}
second function to fill fields depend on choosing ID:
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
//get vaalue of selected project
selectedProject = comboBox1.SelectedItem.ToString();
String selectQuery = "Select * From ubc.BOQ_Table where ID=" + selectedProject;
connection.Open();
MySqlCommand command = new MySqlCommand(selectQuery, connection);
MySqlDataReader reader = command.ExecuteReader();
if (reader.Read())
{
projectNameText.Text = reader.GetString("projectName");
projectName = projectNameText.Text;
companyNameText.Text = reader.GetString("companyName");
projectNumber.Text = reader.GetInt32("projectNumber").ToString();
reader.Close();
}
command.CommandText = "Select itemNum From ubc.BOQ_Table where projectName=" + projectName;
command.ExecuteNonQuery();
while (reader.Read())
{
for (int i = 0; i < reader.FieldCount; i++)
{
comboBox2.Items.Add(reader.GetString("itemNum"));
}
}
reader.Close();
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
connection.Close();
}
This line of code is causing the problem:
command.CommandText = "Select itemNum From ubc.BOQ_Table where projectName=" + projectName;
As commenters have mentioned, concatenating strings is causing both the syntax error and makes your code vulnerable to SQL injection attacks. The solution is to use "parameterized queries" by putting the variable in a MySqlParameter object.
command.CommandText = "Select itemNum From ubc.BOQ_Table where projectName=#projectName;";
command.Parameters.AddWithValue("#projectName", projectName);
using (var reader = command.ExecuteReader())
{
// ...
(You may find some people saying "don't use AddWithValue", but that's an objection that applies just to SqlCommand; there's no good reason to avoid using it with MySqlCommand.)

No value given for one or more required parameters when Changing DropDownlist

Totally two drop downs
Getting values from database like:
Drop DOWN 1(Products)
Ice Cream
Chocolates
Cool Drinks
if from first drop down list 1 selected Ice cream it will display
Drop Down 2(varieties)
Vanilla
Strawberry
Mango
if from first drop down list 1 selected Chocolates it will display
Drop Down 2(varieties)
Dark chocolate
Milk Chocolate
Caramel Chocolate
Other items should clear and displays the above only
Code Used
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
string txtval = DropDownList1.SelectedValue;
string txtval1 = DropDownList1.SelectedItem.Text;
string str = "Provider=Microsoft.ACE.OleDB.12.0; Data Source=C:\\Users\\user\\Desktop\123\\WebSite1\\Checking_Db.mdb";
OleDbConnection db = new OleDbConnection(str);
db.Open();
// string st = "select Emp_Ph_No from emp where Emp_Name = DropDownList1.SelectedValue ;";
string st = "select Emp_Ph_No from emp where Emp_Name = txtval1;";
OleDbCommand dbc = new OleDbCommand(st, db);
OleDbDataReader read = dbc.ExecuteReader();
DropDownList2.DataSource = read;
DropDownList2.DataTextField = "variety";
DropDownList2.DataValueField = ""variety";
DropDownList2.DataBind();
read.Close();
db.Close();
}
Problem on that line;
...where Emp_Name = txtval1;
If txtval1 is a string, you would use it as Emp_Name = 'txtval1'. This is not a valid syntax. In that case, OLEDB provider thinks this txtval1 is a parameter and you didn't suplied any value for that.
You can set this value as a parameter and add to your command like;
string st = "select Emp_Ph_No from emp where Emp_Name = ?";
OleDbCommand dbc = new OleDbCommand(st, db);
dbc.Parameters.AddWithValue("?", txtval1);
I used AddWithValue in my example but you don't. This method may generate unexpected results sometimes. Use .Add() overloads to specify your parameter OleDbType and it's size.
Also use using statement to dispose your connection, command and reader automatically instead of callind .Close or .Dispose methods manually.
using(var db = new OleDbConnection(str))
using(var dbc = db.CreateCommand)
{
// Set your CommandText.
// Add your parameter value.
using(var read = dbc.ExecuteReader())
{
//
}
}

DataReader IndexOutofRangeException was unhandled by user code

I ran into another issue again. I was trying to get data from the database using DataReader but I got the error when i was testing my code. Can anyone help me out? The error occurred at this line:
chkAssess = readAssess[columnName].ToString();
Below is the code snippet:
public string CheckAssess(string emailAddress, string columnName)
{
string chkAssess = "";
SqlDataReader readAssess;
//readAssess = new SqlDataReader();
string MgrAssessQry = "SELECT '"+columnName+"' FROM tblAllUsers";
//MgrAssessQry += " WHERE email ='" + emailAddress + "'";
SqlCommand cmdReadAssess = new SqlCommand(MgrAssessQry, cn);
cn.Open();
readAssess = cmdReadAssess.ExecuteReader();
while(readAssess.Read())
{
// Add the rows
chkAssess = readAssess[columnName].ToString();
}
return chkAssess;
}
try to use column name without ''
select something from table
instead of
select 'something' from table
for security reasons, don't create sql queries in that way (by concatenating strings) - use #parameters instead
2. close the reader at the end
Try this:
public string CheckAssess(string emailAddress, string columnName)
{
string chkAssess = "";
SqlDataReader readAssess;
//readAssess = new SqlDataReader();
string MgrAssessQry = "SELECT #Column_Name FROM tblAllUsers";
SqlCommand cmdReadAssess = new SqlCommand(MgrAssessQry, cn);
cmdReadAssess.Parameters.AddWithValue(new SqlParameter("Column_Name", columnName));
cn.Open();
readAssess = cmdReadAssess.ExecuteReader();
while(readAssess.Read())
{
// Add the rows
chkAssess = readAssess.GetString(0);
}
return chkAssess;
}
You have got several problems here.
Check whether your readAssess has rows like below.
if(readAssess.HasRows)
If it doesn't have rows then trying
chkAssess = readAssess.GetString(0);
would throw this error, as Arrays are index-based.
So your code should be like below
if(readAssess.HasRows)
{
while(readAssess.Read())
{
chkAssess = readAssess.GetString(0);
}
}
Other problem is you need to close both the reader & the connection afterwards.
readAssess.Close();
cn.Close();
Also your code is potentially vulnerable to SQL Injection.
if (reader.HasRows)
{
while (reader.Read())
{
int result = Convert.ToInt32(reader.GetString(0));
Console.WriteLine(result);
}
}
The most important thing is check the query first by executing in SQL Server and see if any result is coming or not.
Secondly based on the type of output you are receiving cast it to that particular data type (important).Mostly everyone is saving the data in varchar so.

set Id equal to number contained in textbox

Hi I want to fill a combo box with names from a table where id is the number contained in textbox.The txtPartId is populated from another page as is the name in txtPart. The error I get when I run this is "Invalid column name "txtPartId"
public ReList(string Str_value, string id)//declare value
{
InitializeComponent();
txtPart.Text = Str_value;
txtPartId.Text = id.ToString();
displayRe();
}
private void displayRe()
{
try
{
sc.Open();
string Query = "select * from Re where Part_PartID =txtPartId ";
SqlCommand createCommand = new SqlCommand(Query, sc);
SqlDataReader dr = createCommand.ExecuteReader();
while (dr.Read())
{
string Name = dr.GetString(1);
cbRe.Items.Add(Name);//Displaying a list in the Combo Box
}
sc.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
The quick and dirty answer is to make the following change:
string Query = "select * from Re where Part_PartID = " + txtPartId.Text;
assuming Part_PartID is an integer.
If it is a string then you can use:
string Query = string.Format("select * from Re where Part_PartID = '{0}'", txtPartId.Text);
The compiler is not going to inject the value of the text in txtPartId into your query string for you.
However, that introduces the scope for SQL injection, so I strongly suggest you parameterize your query. There are many examples of this on SO.

Categories