How can I take the ID as a variable from the Select query in c#.
I have written a query which has to select all IDs with a specific Devicetype.
sqlCommand = new SqlCommand("SELECT Id FROM T_Table1 WHERE DeviceType='" + dev + "'" + "", DbConnect());
int id = (int)sqlCommand.ExecuteScalar();
That's the exception:
An unhandled exception of type 'System.InvalidCastException' occurred in test.exe
Additional information: Specified cast is not valid.
First of all you have to check the database type of your 'id' column. If it is bigint, then use long instead of int.
And secondary you should not add the query string to the select statement. That enables hackers later to run a sql injection against your app or service.
Please use Parameters with the SqlCommand object.
string sql= "SELECT Id FROM T_Table1 WHERE DeviceType=#dev";
SqlCommand command = new SqlCommand(sql, DbConnect());
command.Parameters.Add("#dev", SqlDbType.Text);
command.Parameters["#dev"].Value = dev;
long id = (long)command.ExecuteScalar();
try this
int id =Convert.ToInt32(sqlCommand.ExecuteScalar());
You're calling Execute scalar which will return the first value of the first column of the returned datarow IIRC... So you are trying to take the integer value of null, which others have stated, cannot occur.
I would suggest using the ExecuteEnumerable flavor to return a set of Datarows containing your ID's from T_Table1
using (var myCommand = new SqlCommand())
{
var query = string.Format("SELECT ID FROM T_Table1 WHERE DeviceType='{0}'", dev);
var rows = myCommand.ExecuteEnumerable(query);
foreach (var row in rows)
{
// do whatever to each row
var id = row["ID"];
}
}
If the SELECT query finds no matching value in the database, then the return value of sqlCommand.ExecuteScalar() will be null, if I rembember correctly. And null value cannot be cast to int. You need to check the returned value first before doing the cast. Additionally, you might want to change the type to long instead of int, because an int cannot hold all possible bigint values.
Related
How do I extract data from a data table in a sql server database, knowing that the table could have different column names/column count depending on the request?
I would usually use a SqlDataAdapter and then do: da.Fill(dt) but this is not an option as I cannot enumerate through a dataTable in a razor view. I wish to reproduce that table in a view using Razor Pages.
Here is an example of what I might normally do, but it involves knowing exactly what the column names will be and how many there will be. What can I put in the while to return all of the table data in a type that is enumerable?:
SqlConnection connectionCalc = new SqlConnection("<connectionString>");
if (connectionCalc.State.Equals(ConnectionState.Closed))
connectionCalc.Open();
using (var command = connectionCalc.CreateCommand())
{
command.CommandText = $#"SELECT * FROM {tableName}";
SqlDataReader reader = command.ExecuteReader();
column = new Dictionary<string, string>();
int FATUidSingle = -999;
while (reader.Read())
{
TableUid.Add(reader[SelectedCalculation + "TABLE_UID"].ToString());
FATUid.Add(Convert.ToInt32(reader["FAT_UID"]));
ScheduledDate.Add(Convert.ToDateTime(reader["SOME_DATE"]));
TableStatusUid.Add(reader[SelectedCalculation + "ST_UID"].ToString());
StartDate.Add(Convert.ToDateTime(reader["ANOTHER_DATE"]));
EndDate.Add(Convert.ToDateTime(reader["OTHER_DATE"]));
Progress.Add(reader["PROGRESS"].ToString());
}
Run a command like this first to get the field names, then you will know which fields to expect. You could use it to build SQL and set ordinals to point to the column you want
SELECT TABLE_NAME, COLUMN_NAME FROM
INFORMATION_SCHEMA.COLUMNS
where table_name = 'EmployeeDetail'
when you make your enumerable list, make a list of 'tuples' of string and object perhaps, where the string is the field name and the object is the value
If you only worry about exact names but you know column sequence and datatype then you could simply rely on index of column from select statement.
E.g
Select * from Orders
Order table might have 3 columns. Id, Name and Price where id is int, Name is string and Price is long.
So you can do:
var id = reader.GetInt32(0);
var name = reader.GetString(1);
var price = reader.GetInt64(2);
I'm trying to find a way to have access to all the values in a row.
The following code returns one cell. If I change select id to select *, I have access to the row but how can I break it apart?
string find_user = "select id from users where userName = '" + un + "'";
using (SqlConnection con = new SqlConnection(cs))
{
using (SqlCommand cmd = new SqlCommand(find_user, con))
{
con.Open();
user_id = cmd.ExecuteScalar().ToString();
/* use to pass the info to all the pages */
Session.Add("u_id", user_id);
}
}
You cannot access additional columns using .ExecuteScalar(), per the docs:
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.
Although it is not a route that I would recommend, you can iterate through the fields by using an index on a data reader:
SqlDataReader dataReader = cmd.ExecuteReader();
// for the query's result set, this while loop will go through all the records
while (dataReader.Read())
{
// for the current record, this for loop will go through all the fields
for (int i = 0; i < dataReader.FieldCount; i++)
{
var value = dataReader[i]; // do what you need with the data here
}
}
A better approach would be to specify the field names in the SQL query instead of using SELECT *, then get the values from the data reader by the specific field names (not relying on the order of the fields in the DB).
Also, you have a SQL injection vulnerability. You should look up what this means and how to parameterize a query.
I want to access my SQL Server database and retrieve the value of some columns with specific id. I get the id as a print the database in a dataGridView table, so the first cell of the row that the user has selected is the id. Here is the code
con3.Open();
if (typeBOX.SelectedIndex == 0)
{
pictureBox1.Image = Organizer.Properties.Resources.b_height_years;
ChartForm.ImageSet = 1;
pictureBox1.Invalidate();
SqlCommand cmd1 = new SqlCommand("select Height,Age from data where Id = '" + dataGridView1.SelectedCells[0].Value.ToString() + "'", con3);
// SqlCommand cmd2 = new SqlCommand("select Age from data where Id = '" + dataGridView1.SelectedCells[0].Value.ToString() + "'", con3);
SqlDataReader reader1 = cmd1.ExecuteReader();
bool flag = false;
while (reader1.Read() && flag == false)
{
string tempHeight = reader1["Height"].ToString();
ChartForm.Height = int.Parse(tempHeight);
string tempAge = reader1["Age"].ToString();
ChartForm.Age = int.Parse(tempAge);
flag = true;
}
}
But when I am trying to run the code I get the error:
System.Data.SqlClient.SqlException: 'Conversion failed when converting the varchar value 'zxxv' to data type int.
'zxxv' is a saved FirstName in the database but I do not for it in my command cmd1. I am only accessing the height and age which are both integers. I do not know why this is happening.
I bet you received that error because you tried to pull the Id out of the wrong cell in the data. The error message states that an error occurred while trying to convert value 'zxxv' to int. That would mean that the value stored in:
dataGridView1.SelectedCells[0]
is 'zxxv'. An error is occurring when the SQL Server attempts to compare that value to an int column. It looks like maybe you clicked on the cell in the dataGridView1 that contained the first name, but the id is in a different column, or is hidden. This is just a wild guess, but it's the best I can do without having the rest of your code. Would something like this fix it?
dataGridView1.SelectedRows[0].Cells[0].Value
or:
dataGridView1.SelectedRows[0].Cells["Id"].Value
I totally agree with the others who said you should pass the id in as a parameter. You should do that too. But I don't think the lack of a parameter is what is causing the error.
The problem is you're passing the Id as a string, not an int. So, the error is telling you that the SQL server failed to convert the string into an int. The reason this is happening is because the Id is wrapped in single quotes which SQL will interpret as a string (varchar/nvarchar).
I'd recommend to always parameterise your SQL query to avoid potential attacks through SQL injection and problems like this one. Please see Why do we always prefer using parameters in SQL statements?.
You also need to ensure you're selecting the correct value from the dataGridView as #RussW mentions in their answer. You're selecting the FirstName field, so perhaps you could use:
int selectedRowIndex = datagridview1.SelectedCells[0].RowIndex;
DataGridViewRow selectedRow = datagridview1.Rows[selectedRowIndex ];
int id = int.Parse(selectedRow.Cells["Id"].Value.To);
Or
int rowIndex = dataGridView1.CurrentCell.RowIndex;
int columnIndex = dataGridView1.CurrentCell.ColumnIndex;
int id = int.Parse(dataGridView1.Rows[rowIndex].Cells[columnIndex].Value.ToString());
Below is a sample which should get you started:
string query = "select Height, Age from data where Id = #id"; // parameter #id in string
SqlCommand cmd1 = new SqlCommand(query, con3); // create command with string
// get the correct row and cell
int selectedRowIndex = dataGridView1.SelectedCells[0].RowIndex;
DataGridViewRow selectedRow = dataGridView1.Rows[selectedRowIndex];
int id = int.Parse(selectedRow.Cells["Id"].Value.ToString()); // parse id to int
// create sql parameter and add to SqlCommand
SqlParameter param1 = new SqlParameter("#id", id);
cmd1.Parameters.Add(param1);
// continue your code...
SqlDataReader reader1 = cmd1.ExecuteReader();
....
Note, when using parameterised queries there's no need to wrap the parameter in quotes, it is handled for you. Please refer to the SqlCommand.Parameters docs.
How to count number of rows in table while using a where condition in the same query.
I am using below query to get the number of rows where departmentname is equal to electrical engineering.But this is now working what is the correct query
SqlCommand cmd1 = new SqlCommand("Select count(*) from Student
where DepartmentName = 'DepartmentOfElectricalEngineering' ");
cmd1.Connection = conn;
studentdata[4] = cmd1.ExecuteScalar().ToString();
Not a lot of information. What is the ExecuteScalar function returning? Nothing? Is there an exception? what is studentdata[4]? ExecuteScalar returns an object, which you need to cast depending on the field (int in this case) and the variable where you're storing it. Did you try to run this query against SQL Server directly? Have you tried specifying an explicit field name, like this:
Select count(*) as C from Student
where DepartmentName = 'DepartmentOfElectricalEngineering'
I am trying to find the MAX number from a database field,The query below returns me the maximum value if i run it in SQL Enterprise Manager but i am not able to print the value in numbwe. Please help me to print the MAX value obtained from the database.
SqlConnection MyConnection = new SqlConnection("Data Source=localhost;Initial Catalog=hcgoa;User Id=sa;Password=;");
SqlCommand MyCmd = new SqlCommand("SELECT MAX([no]) AS Expr1 FROM jmain", MyConnection);
MyConnection.Open();
SqlDataReader myReader = MyCmd.ExecuteReader();
if (myReader.Read())
{
string numbwe = myReader["no"].ToString();
Response.Write("Max no. is : " + numbwe);
}
You need to use Expr1 as the key, not no.
That's because you're doing:
SqlCommand MyCmd = new SqlCommand("SELECT MAX([no]) AS Expr1 ...
(note the AS clause) so the column is named Expr1. Hence:
string numbwe = myReader["Expr1"].ToString();
should do it.
Although, in fairness to those who come after you, Expr1 is not a very descriptive identifier. Consider the possibility of changing it to something like MaxNum (both in the select and the key, of course).
You should look at the ExecuteScalar() instead if you are going to return a single value.
MSDN: Use the ExecuteScalar method to
retrieve a single value (for example,
an aggregate value) from a database.
This requires less code than using the
ExecuteReader method, and then
performing the operations that you
need to generate the single value
using the data returned by a
SqlDataReader.
You're trying to print the value of a column that doesn't exist in the query result. Your query returns a column named Expr1, not a column named "no"
Change
string numbwe = myReader["no"].ToString();
to
string numbwe = myReader["Expr1"].ToString();
should be string numbwe = myReader["Expr1"].ToString();
as you are specifying your column name in sql statement Expr1
SELECT MAX([no]) AS Expr1