My SQL query is not working. The query is something like this:
QueryString = SELECT material FROM tbl1 WHERE vendor = UserInputVar;
This query would run after the UserInputVar was made by the user from selecting a value in a combobox(say, combobox1). What this query does is that the results fetched by this query will populate another combobox(say, combobox2).
I tried to find the solution online but nothing works on my current problem. I tried to do it on my own by trying the following:
Use MySqlDataAdapter together with MySqlCommandBuilder, then use the adapter to fill a data table and that data table would be the datasource
Put QueryString and connect_DBstring in a MySqlCommand constructor and use a variable instance of MySqlCommand. Then, use adapter and commandbuilder to fill the datasource of second combobox.
Any suggestions and links would help. I really don't know what to do since I usually use MySqlDataReader for SELECT statements and MySqlDataAdapter for INSERT statements. I haven't had an experience using SELECT with MySqlDataAdapter before
Don't use user input in SQL statement since it creates possibility to make SQL injections.
using (MySqlConnection connection = new MySqlConnection(con))
{
try
{
connection.Open();
using (MySqlCommand command = connection.CreateCommand())
{
command.CommandText = "SELECT material FROM tbl1 WHERE vendor=#vendor"
command.Parameters.AddWithValue("#vendor", UserInputVar);
command.ExecuteNonQuery();
connection.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
As for populating combobox from SQL query take a look at the following post:
https://stackoverflow.com/a/12495086/1099716
I managed to solved the problem. It turns out my way of parameterized query is wrong but I finally corrected it. Instead of using MySqlCommand parameters, I used MySqlDataAdapter parameters instead. I never knew about it at first but thankfully I know now.
Related
For example, I have a script that contains
insert into #temp from TABLES
insert into #temp1 from #temp
select * from #temp
I already have a C# MVC application. I just want to be able to execute the script above to display the #temp table on my front-end. I have seen the function ExecuteNonQuery(), however, it only shows the rows affected. Is there anyone that can point me a guide to solve this issue?
EDIT: I just want to run the script above and obtain the results, i don't want to rewrite the script in a framework.
Here is a sample for ExecuteNonQuery:
private void ExecuteNonQuery(string queryString, string connectionString)
{
using (SqlConnection connection = new SqlConnection(
connectionString))
{
SqlCommand command = new SqlCommand(queryString, connection);
command.Connection.Open();
command.ExecuteNonQuery();
}
}
From MSDN
And you can call your inserts like this: ExecuteNonQuery("insert into #temp from TABLES", connectionString);
For reading you can use ExecuteReader (MSDN) But if your table has many columns, this can be tedious to display all the columns. I prefer to use micro ORM (or data mapper otherwise) like Dapper - it is easy to use, minimum set up and with plenty of documentation.
Some people advise to use Entity Framework, but for this case it looks like will be an overkill. Also it has a steep learning curve.
If you want to read data from temporary table so use the ExecuteReader() and refer the following code.
using(SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
var myString = rdr.GetString(0); //The 0 stands for "the 0'th column", so the
first column of the result.
// Do somthing with this rows string, for example to put them in to a list
listDeclaredElsewhere.Add(myString);
}
}
For select you have can use DataSet object and using DataAdapter fill data to DataSet
DataSet ds=new DataSet();
SqlDataAdapter da=new SqlDataAdapter(commandObject);
da.fill(ds);
DataSet ds=new DataSet();
SqlDataAdapter da=new SqlDataAdapter(commandObject);
da.fill(ds);
yes, that would work as well. but be aware that you are working with a DataSet (not DataTable on purpose?), and both DataSet and it's matching DataTable(s) are all dynamic objects without type safety (i.e. you are working with ds.Tables[0].Rows[0][2] as string; ).
good luck with the runtime exceptions.
I know this error/question has been posted a lot. Iv been researching for a while now and still cannot figure how to properly update my database with changes made in my DataTable.
I have a DataTable filled with information from 2 different tables in my database. Changes are only being made to the columns that come from 1 table though. The second table I need to JOIN for calculations.
So when I try to update my database, changes will only be made to the 1 table. I am still need to ado.net, so im having a hard time applying the correct way to apply these changes based on information from MSDN and StackOverflow.
This is the code I have:
using (SqlCommand cmd = new SqlCommand("SELECT INCIDENT_NO, report_dt,MIN(theStart) as The_Start, Resolved_DT, Resolution_TIME, resolution_met,response_met,max_response_time,max_resolution_time,impact FROM TICKET_REPORT JOIN TimeTracker ON Incident_NO=theTask WHERE Resolved_DT != '' GROUP BY INCIDENT_NO,report_dt,Resolved_DT,Resolution_Time, resolution_met,response_met,max_response_time,max_resolution_time,impact", sqlConn))
{
var calc = new Calculation(holidays, new OpenHours("09:00;17:00"));
SqlDataAdapter da = new SqlDataAdapter(cmd);
dtResolution.Columns.Clear();
dtResolution.Clear();
da.Fill(dtResolution);
//-------Making calculation changes to columns from one table in datatable here---------
try
{
da.Update(dtResolution);
Console.WriteLine("Update successful");
}
catch(Exception ex)
{
Console.WriteLine("Updated failed");
Console.WriteLine(ex.Message);
}
da.Dispose();
}
I leaned that CommandBuilder will create the update command for me, but MSDN says I can only use CommandBuilder if my SELECT statement only includes 1 table, I have 2 two.
Other StackOverflow answers are saying that if im using a JOIN, im on my own.
How can I properly accomplish this update? Can I do this in C#? Should I pass the data table to a stored procedure in sqlserver instead?
I found it easier to just create a merge statement inside of a stored procedure, and just pass the datatable to the stored procedure.
I'm trying to set up so that the table name is passed to the command text as a parameter, but I'm not getting it to work. I've looked around a bit, and found questions like this: Parameterized Query for MySQL with C#, but I've not had any luck.
This is the relevant code (connection == the MySqlConnection containing the connection string):
public static DataSet getData(string table)
{
DataSet returnValue = new DataSet();
try
{
MySqlCommand cmd = connection.CreateCommand();
cmd.Parameters.AddWithValue("#param1", table);
cmd.CommandText = "SELECT * FROM #param1";
connection.Open();
MySqlDataAdapter adap = new MySqlDataAdapter(cmd);
adap.Fill(returnValue);
}
catch (Exception)
{
}
finally
{
if (connection.State == ConnectionState.Open)
connection.Close();
}
return returnValue;
}
If I change:
cmd.CommandText = "SELECT * FROM #param1";
to:
cmd.CommandText = "SELECT * FROM " + table;
As a way of testing, and that works (I'm writing the xml from the dataset to console to check). So I'm pretty sure the problem is just using the parameter functionality in the wrong way. Any pointers?
Also, correct me if I'm mistaken, but using the Parameter functionality should give complete protection against SQL injection, right?
You can not parameterize your table names, column names or any other databse objects. You can only parameterize your values.
You need to pass it as a string concatenation on your sql query but before you do that, I suggest use strong validation or white list (only fixed set of possible correct values).
Also, correct me if I'm mistaken, but using the Parameter
functionality should give complete protection against SQL injection,
right?
If you mean parameterized statements with "parameter functionality", yes, that's correct.
By the way, be aware, there is a concept called dynamic SQL supports SELECT * FROM #tablename but it is not recommended.
As we have seen, we can make this procedure work with help of dynamic
SQL, but it should also be clear that we gain none of the advantages
with generating that dynamic SQL in a stored procedure. You could just
as well send the dynamic SQL from the client. So, OK: 1) if the SQL
statement is very complex, you save some network traffic and you do
encapsulation. 2) As we have seen, starting with SQL 2005 there are
methods to deal with permissions. Nevertheless, this is a bad idea.
There seems to be several reasons why people want to parameterise the
table name. One camp appears to be people who are new to SQL
programming, but have experience from other languages such as C++, VB
etc where parameterisation is a good thing. Parameterising the table
name to achieve generic code and to increase maintainability seems
like good programmer virtue.
But it is just that when it comes to database objects, the old truth
does not hold. In a proper database design, each table is unique, as
it describes a unique entity. (Or at least it should!) Of course, it
is not uncommon to end up with a dozen or more look-up tables that all
have an id, a name column and some auditing columns. But they do
describe different entities, and their semblance should be regarded as
mere chance, and future requirements may make the tables more
dissimilar.
Using table's name as parameter is incorrect. Parameters in SQL just works for values not identifiers of columns or tables.
One option can be using SqlCommandBuilder Class, This will escape your table name and not vulnerable to SQL Injection:
SqlCommandBuilder cmdBuilder = new SqlCommandBuilder();
string tbName = cmdBuilder.QuoteIdentifier(tableName);
You can use the tbName in your statement because it's not vulnerable to SQL Injection now.
This is bugging me. Something so simple and it does not work. What could I be doing wrong?
Here is the code I am using ...
string strSQL = "SELECT ac.ContactEmail AS fldEmail FROM vwApprenticeshipContactDetails ac WHERE (ac.ApprenticeshipID = #ApprenticeshipID)";
SqlCommand cmd2 = new SqlCommand(strSQL, cnn);
cmd2.Parameters.Add("#ApprenticeshipID", SqlDbType.Int).Value = wsAppID;
Object fldEmail = cmd2.ExecuteScalar();
Believe it or not, the above returns what looks like an array when I debug and look at the value of 'fldEmail'. In otherwords it's empty, nothing or null (cannot tell as the output window shows an array). I have run this directly in SQL server and I get the email showing fine. Could the '#' character inside the database field be causing something here?
The email I expected back is 'g.somebody#domain.com.au', which to me looks ok.
UPDATE
I replaced the ContactEmail field above, with another column name from the database and it comes back fine. Not sure why emails are an issue. The datatype by the way here is VARCHAR(50).
UPDATE
In debug mode I noticed it returns system.DBNull data type (and digging deeper it returns empty), but why? I ran the exact same query with the correct parameter in SQL server and I get a email showing. Strange
Thanks
Solved it!
For some reason (and I am a noob when it comes to email objects in C#), but an ExecuteScalar is not properly populating as it was not "read" first. What I mean by this is that when I changed ExecuteScalar to an SqlReader, it worked because I am "forcing" the read of the SQL before testing it.
So my code looks now like this and it returns an email!
strSQL = #"SELECT TOP 1 ContactEmail FROM vwApprenticeshipContactDetails WHERE ApprenticeshipID = #ApprenticeshipID";
SqlCommand cmd2 = new SqlCommand(strSQL, cnn);
cmd2.Parameters.Add("#ApprenticeshipID", SqlDbType.Int).Value = wsAppID;
using (SqlDataReader rdr = cmd2.ExecuteReader())
{
string fldEmail = "support#domain.com.au"; //this is as a default in case the sql above does not return a value
while (rdr.Read())
{
fldEmail = rdr.GetSqlValue(0).ToString();
}
}
I was avoiding SqlReader initially because I thought they were specifically designed for when reading in more than one row of data. In my case I know the parameter given only returns one row or nothing at all.
Thanks
At the first change select to top 1 for performance reason.
string strSQL = "SELECT Top 1 ac.ContactEmail AS fldEmail FROM ...
If you dont have any result in query, you will get null value as result.
You can check how many records returned by query in sql server profiler.
Also you can check your connection string to make sure are you connected to correct database.
I am writing a C# WPF application with controls bound to a MySQL 5.5 database. I'm populating a DataTable using a MySqlDataAdapter, passing in a MySQL SELECT query.
When the query is something trivial, like SELECT * FROM People or SELECT LastName, FirstName, PersonID FROM People, all is well and my ListBox control ends up populated with the expected names.
When the query contains a fairly simple CONCAT operator, though, the query silently fails and the ListBox stays empty. In particular neither of the following have worked, even though both work fine from within the MySQL command line.
SELECT CONCAT(LastName, FirstName) as Name FROM People
SELECT CAST(CONCAT(LastName, FirstName) AS CHAR) as Name FROM People
Both LastName and FirstName are defined as VARCHAR. So, I wouldn't expect this to be an instance of CONCAT returning a binary string in any case. I mention that because it appears to have been the problem for similar issues that other folks have mentioned.
I'd imagine the DataAdapter attempts to parse your query into an internal format so that it can do things like generate Update and Insert commands.
Can you fill your datatable using a MySqlDataReader instead? This is probably only helpful if you are not planning to do database updates with the DataTable
Going from memory...
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataReader reader = cmd.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(reader);