Database problem in visual studio (c# and SQL Server) - c#

I am writing a Windows Forms app in which I have to simulate keeping count of who is missing in class. I have made a database inside Visual Studio which works well. I also found a tutorial on youtube on how to do it, so I did it. In one part of the video he puts an "#(Name of the variable in the table)" instead of a value in query. For him it works, for me it doesn't and i don't know why. Please help.
private void napuniUcenici()
{
string query = "SELECT a.Ime FROM Ucenici a " +
"INNER JOIN RazrediUcenici b ON a.Id = b.UcenikId " +
"WHERE b.RazredId = #RazredId";
using (connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(query, connection))
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
command.Parameters.AddWithValue("#RazredId", lstUcenici.SelectedValue);
DataTable uceniciTable = new DataTable();
adapter.Fill(uceniciTable);
lstUcenici.DisplayMember = "Ime";
lstUcenici.ValueMember = "Id";
lstUcenici.DataSource = uceniciTable;
}
}
This happens when I call this function in my code. And it returns this massage:
System.Data.SqlClient.SqlException:
'The parameterized query
'(#RazredId nvarchar(4000))SELECT a.Ime FROM Ucenici a INNER JOIN'
expects the parameter '#RazredId', which was not supplied.'
Also, RazredId isn't a navchar(4000), it is a regular integer. The guy in the video didn't have this problem.
The video: https://www.youtube.com/watch?v=_PCBTiXL884
[1
[2
[3

try to pass an explicit value instead:
command.Parameters.AddWithValue("#RazredId", 1);
and see whats's happen. It is correct to retain the # in the param name, unlike as previous repolies.

Ok guys, so... I am dumb xD
What i did wrong is that the second parameter in this line was wrong(the lstRazredi was previously lstUcenici which is the wrong table)
command.Parameters.AddWithValue("#RazredId", lstRazredi.SelectedValue);
So i changed that and now i works perfectly.
Sorry for bothering.

Maybe you need to add the parameter before you pass the command to the adapter?

Related

Comparing a string to it's equal in a database returns false

I would like to find in my database which line has its "path" field's value equal to the string "c:\something\somethingelse\anotherthing.thing".
I found the line by browsing and copied it's content, before making an SQL request:
On C# side, my code looks like this:
EDIT: Due to #CompuChip 's comment, I edited my line for something that I hope may be better
String MyPath = "c:\\something\\somethingelse\\anotherthing.thing"
MyPath = String.Format("select * from x where path = '{0}'", MyPath);
Then I called the method to create and send the request to my database but I got an exception
I tried the request itself on my database but even if I copied the exact value it couldn't find the line:
Here's what I tried:
Select * from x where path = "c:\something\somethingelse\anotherthing.thing"
Select * from x where STRCMP(path, "c:\something\somethingelse\anotherthing.thing") = 0
Is there a good way to compare the strings correctly and find my line ?
Thank you for your time and have a nice day.
Edit 2: I also tried getting all my lines in C# then comparing them one by one.
It worked, but with 10K+ lines it's beginning to consume resources
Please, please, please don't construct your SQL queries like that.
The proper solution is using parameters, as explained here:
Why do we always prefer using parameters in SQL statements?
Your C# code would become something like this (adapted from the linked answer):
string sql = "select * from x where path = #path";
using (SqlCommand command = new SqlCommand(sql, connection))
{
var pathParam = new SqlParameter("path", SqlDbType.VarChar);
pathParam.Value = #"c:\something\somethingelse\anotherthing.thing";
command.Parameters.Add(pathParam);
var results = command.ExecuteReader();
}
or, for MySql,
string sql = "select * from x where path = ?path";
using (MySqlCommand command = new MySqlCommand(sql, connection))
{
var pathParam = new MySqlParameter("path",
#"c:\something\somethingelse\anotherthing.thing");
command.Parameters.Add(pathParam);
var results = command.ExecuteReader();
}
Assuming that you (have checked that you) actually have a matching record in the database, the problem is likely either with the quoting, or the escaping of the value.
If that is indeed the case, using parameters to retrieve the record is not only the safe thing to do, it will also make your quoting or escaping problem a non-issue.
It appears I have to do the same thing I do in C# and put two backslashes instead of one in the path, even in MySQL
Furthermore I also had to construct correctly my requests as #CompuChip hinted.
Thank you all for your help !

Problem with Syntax Error in SQL statement

I am trying to get a specific single value from an Access Database using C#.
For some reason what I am asking for is giving me an exception of
Syntax error in FROM clause
and I cant work out why.
I have tried running the SQL directly in Access itself and it works fine and gives me back the results I want, but I have no idea why its not working in my program.
ProbID is a number field as far as Access describes it and CorrDetails is a memo field.
For simplicity i have set the SQL to look for a specific value (137) but once i have the code working i will make it paramiterised.
Any ideas?
string corrAct;
OleDbConnection dbConnection;
dbConnection = new OleDbConnection(vDbString);
string sqlString = "SELECT CorrDetails FROM Action WHERE ProbID=137";
OleDbCommand command = new OleDbCommand(sqlString, dbConnection);
using (dbConnection)
{
MessageBox.Show(sqlString);
dbConnection.Open();
corrAct = (String)command.ExecuteScalar();
rtfCorrectiveAction.Text = Convert.ToString(corrAct);
dbConnection.Close();
}
Action is a reserved word in MS Access.
Wrap it with []:
string sqlString = "SELECT CorrDetails FROM [Action] WHERE ProbID=137";
The problem is you havent taken into account keywords in SQL. https://learn.microsoft.com/en-us/sql/odbc/reference/appendixes/reserved-keywords?view=sql-server-ver15
Action is a keyword so should not be used really in another context, to use them put [] round them some it becomes
select stuff from [Action] where stuff=true

Parameterized SQL queries don't work

I have posted this question already because I had problems with the "LIKE" statement but now I realized there are problems with parameterized statements at all. Here is my code:
for example when I write:
sqlCmd = new SqlCommand(#"SELECT #cusId,#cusName FROM " + form1.getTable() + " WHERE #cusId LIKE #filter", connection);
sqlCmd.Parameters.AddWithValue("cusId", form1.cusId.Text);
sqlCmd.Parameters.AddWithValue("cusName", form1.cusName.Text);
sqlCmd.Parameters.AddWithValue("filter", form1.filterType().Trim() + "%");
sqlDatAdapter = new SqlDataAdapter(sqlCmd.CommandText, connection);
sqlDatAdapter.Fill(datTable);
form1.setDataGrid = datTable;
Somehow I always get
"Must declare the scalar variable #..."
for each variable when I fill the data table. I tried that already with
sqlCmd.ExecuteNonQuery();
and it seems to work in this case (when I update a database it works fine) but I need to bind the values to my DataGridView.
EDIT: Even when I just try to write something like:
... WHERE cusId.Text = #cusId
I get the same error
As noted, you aren't working with parameters quite right. Your SqlCommand should be something more like this:
SqlCommand sqlcmd = new SqlCommand(#"SELECT cusId,cusName FROM " + form1.getTable() + " WHERE cusId LIKE #filter", connection);
Note how the columns you are trying to select aren't parameters (so don't include '#' symbol).
When you add parameters you DO need to add the '#' symbol. Something like this:
sqlCmd.Parameters.AddWithValue("#cusId", form1.cusId.Text);
You can't parameterize your table and column names . You can only parameterize your values.
If you really wanna get your table and column names dynamically, you can use dynamic SQL but which is a bad idea.
Best way to get your column names dynamically is creating a strong validation for your column names or creating a black list for them.
Using ExecuteNonQuery doesn't effect anything since it's because just execute your query, does not return any data. Also use using statement to dispose your connections, commands and adapter.
Here an example;
string str = string.Format("SELECT {0}, {1} FROM {2} WHERE {0} LIKE #filter",
form1.cusId.Text,
form1.cusName.Text,
form1.getTable());
sqlCmd = new SqlCommand(str, connection);
sqlCmd.Parameters.AddWithValue("#filter", form1.filterType().Trim() + "%");
sqlDatAdapter = new SqlDataAdapter(sqlCmd);
sqlDatAdapter.Fill(datTable);
But I have to say again, you really need strong validation or black list for your column and table name when you try get them outside of your program.
I used AddWithValue in this example but this method might be dangerous in some cases. Using .Add() overloads to specify it's db type and parameter size implicitly would be better.
Finally solved it! I tried:
using (sqlDatAdapter = new SqlDataAdapter(sqlCmd.CommandText, connection))
{
sqlDatAdapter.SelectCommand.Parameters.Add("#filter", SqlDbType.Int, 25).Value = CusIdEnter;
sqlDatAdapter.Fill(datTable);
form1.setDataGrid = datTable;
}
and now it works! One had to bind the parameters to the Adapter

c# Update Command to Access Database

I am trying to update data in access table. However, i keep receiving a syntax error when i attempt to update. Below is the code ive compiled. Textbox37 is the one that requires updates.
string constr1;
constr1 = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=F:\\Documents\\data.accdb;Jet OLEDB:Database";
string cmdstr = "Update Log(Notes,Status)Values(#a,#b) Where LogIncNum='" + LogInc + "'";
using (OleDbConnection con1 = new OleDbConnection(constr1))
{
using (OleDbCommand com = new OleDbCommand(cmdstr, con1))
{
com.CommandType = CommandType.Text;
com.Parameters.AddWithValue("#a", textBox37.Text);
com.Parameters.AddWithValue("#b", "Active");
con1.Open();
com.ExecuteNonQuery();
}
}
The correct syntax for an update statement is
UPDATE table SET field1=value1, field2=value2 WHERE field3=value3
You are using the wrong syntax hence the syntax error
As a side note, did you forget to use a parameter for the WHERE condition?
It is always correct to use a parameter for every value that you want to include in your query. Just remember to put it in the correct order because OleDb doesn't recognize the parameter by their name, but use a strictly positional order in the Parameters collection, so the first one goes assigned to the first parameter placeholder and so on.
easy way
using (var aq_pension = new System.Web.UI.WebControls.SqlDataSource())
{
aq_pension.ProviderName = "System.Data.OleDb";
aq_pension.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:/stat_tresor/stat_tresor/stat_tresor/db/stat1.mdb";
aq_pension.UpdateCommand = "UPDATE tableaux1 SET nbre=0, montant_mois=0,total=0 WHERE code <>''";
aq_pension.Update();
}

SQL Parameters Inside A Loop

i have a list that i am pulling things out of to insert into a database. This is not going to be a web app so i have just been doing as follows:
string sqlStorage = (null,"asd"),
for (int i = 1; i < listsize; )
{
sqlStorage = sqlStorage + "(null,someVariableFromLoop)";
i++
}
string connString = "Server=localhost;...........";
MySqlConnection conn = new MySqlConnection(connString);
MySqlCommand command = conn.CreateCommand();
command.CommandText = #"INSERT INTO table1 VALUES " + tempSQLStorage;
etcetc...
However
"someVariableFromLoop"
is a large amount of text which includes all kinds of horrible code breaking characters. quotation marks etc etc.
So i looked into parameters (the way i should be doing SQL i know, i know), however i was unable to find a way to store these parameters inside the loop. i dont want to hit the DB every single iteration. I had a go at something along the lines of
"#variable"+i.toString();
but could not get it to work at all.
So does anyone have any idea how i would go about storing the parameters and the execute the query? Thanks in advance!
So i looked into parameters (the way i should be doing SQL i know, i know), however i was unable to find a way to store these parameters inside the loop. i dont want to hit the DB every single iteration. I had a go at something along the lines of
"#variable"+i.toString();
but could not get it to work at all.
Well, what was the error you received? Because that's the way you do it. Here's an example for MSSQL and I know the technique works, because I've done similar before:
int i = 0;
List<string> clauses = new List<string>() {"(#key0, #value0)"};
List<SqlParameter> paramList = new List<SqlParameter> {
new SqlParameter("#key0", DBNull.Value),
new SqlParameter("#value0", "asd")
};
for (i = 1; i < listSize; i++) {
clauses.Add("(#key" + i + ", #value" + i + ")");
paramList.Add(new SqlParameter("#key" + i, someKey));
paramList.Add(new SqlParameter("#value" + i, someValue);
}
SqlConnection conn = new SqlConnection(connString);
SqlCommand command = new SqlCommand(conn, #"INSERT INTO table1 VALUES " + String.Join(", ", clauses);
foreach(SqlParameter param in paramList) command.Parameters.Add(param);
command.ExecuteNonQuery();
Note, above code is quick and dirty. Obviously using statements and various other best practices should be incorporated as well for production code.
Also look at this: How do you use the MySql IN clause. It has an example of dynamically creating and passing parameters to the query, but for an SELECT...IN clause vs. INSERT...VALUES.
To ensure secure code (and avoid malformed queries), use SQL Command objects with Parameters. There is nothing horribly wrong with executing the command once for every record - a little extra overhead for round-trips over the network, but if the text is long you might have to do this anyway since queries do have a character limit.

Categories