OLEDB Parameterized Query - c#

public void LoadDB()
{
string FileName = #"c:\asdf.accdb";
string query = "SELECT ID, Field1 FROM Table1 WHERE ID=? AND Field1=?";
string strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + FileName;
OleDbConnection odc = new OleDbConnection(strConn);
dAdapter = new OleDbDataAdapter();
OleDbCommand cmd = new OleDbCommand(query,odc);
cmd.Parameters.Add("?", OleDbType.Integer, 5).Value = 1234;
cmd.Parameters.Add("?", OleDbType.BSTR, 5).Value ="asdf";
dAdapter.SelectCommand = cmd;
ds = new DataSet();
dAdapter.Fill(ds);
dataGridView1.DataSource = ds.Tables[0];
}
I'm trying to use parametrized query to bind the access file into the datagridview. It finds the column names fine, but the contents are empty.
How can I fix this issue?

Here is an example of how the parameterized queries work with CSharp, OleDB.
try
{
connw.Open();
OleDbCommand command;
command = new OleDbCommand(
"Update Deliveries " +
"SET Deliveries.EmployeeID = ?, Deliveries.FIN = ?, Deliveries.TodaysOrders = ? , connw);
command.Parameters.Add(new OleDbParameter("#EMPID", Convert.ToDecimal(empsplitIt[1])));
command.Parameters.Add(new OleDbParameter("#FIN", truckSplit[1].ToString()));
command.Parameters.Add(new OleDbParameter("#TodaysOrder", "R"));
catchReturnedRows = command.ExecuteNonQuery();//Commit
connw.Close();
}
catch (OleDbException exception)
{
MessageBox.Show(exception.Message, "OleDb Exception");
}
This will work with any sql statement, you must assign the question mark "?" to each parameter, and then below you must create the parameters and add them in the order of how you laid out the question marks to get the right data into the right field.

In my test program, the ds.Tables[0].Rows.Count datatable actually had 1 row returned (as there was one row in my test database that matched the query itself). If you put a break on this line you should be able to see whether or not data is getting into the datatable in the first place. Try this:
dataGridView1.DataSource = ds.Tables[0];
What does the front end binding of dataGridView1 look like? Running the query in Access could shed some light on the situation too.

Try without specifying column size in parameters:
cmd.Parameters.Add("?", OleDbType.Integer).Value = 1234;
cmd.Parameters.Add("?", OleDbType.BSTR).Value ="asdf";

Related

How does sanitize the sql parameter

I write these code all are working fine but there is a warning coming that sanitize the sql parameter.
private DataSet ExcelToDataSet(string fileData)
{
DataSet ds = new DataSet();
string connectionString = GetConnectionString(fileData);
using (OleDbConnection conn = new OleDbConnection(connectionString))
{
conn.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = conn;
// Get all Sheets in Excel File
DataTable dtSheet = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
// Loop through all Sheets to get data
foreach (DataRow dr in dtSheet.Rows)
{
string sheetName = dr["TABLE_NAME"].ToString();
if (!sheetName.EndsWith("$"))
continue;
// Get all rows from the Sheet
cmd.CommandText = "SELECT * FROM [" + sheetName + "]";
DataTable dt = new DataTable();
dt.TableName = sheetName;
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
da.Fill(dt);
ds.Tables.Add(dt);
}
cmd = null;
conn.Close();
}
return (ds);
}
I have to sanitize the following line
cmd.CommandText = "SELECT * FROM [" + sheetName + "]";
Usually, when writing SQL Statements, you need to use parameters to pass the data from user input into the sql statement, to prevent SQL Injection attacks. That's why you get this warning. However, there is nothing you can do about it since it's impossible to parameterize identifiers in SQL, and you don't need to do it because you are not concatenating user input, and you are not running this query on a database, so even if you could use SQL injection, the worst you can do is corrupt a single file
UPDATE: I did not notice this was a OleDbConnection, the database you are connecting to may not have the same functionality to quote an identifier. I am leaving this answer here in case someone comes across this question and needs the same thing but for a SQL connection.
As the others have said, there is no need to worry about the warning in this case as the data is not coming from user data.
However everyone is wrong about the fact you cannot parameterize an identifier. You need to build the query dynamically server side and use the QUOTENAME function but it is possible.
foreach (DataRow dr in dtSheet.Rows)
{
string sheetName = dr["TABLE_NAME"].ToString();
if (!sheetName.EndsWith("$"))
continue;
// Get all rows from the Sheet
cmd.CommandText = #"
declare #sql nvarchar(114);
set #sql = N'select * from ' + quotename(#sheetname)
exec sp_executesql #sql
";
cmd.Parameters.Clear();
cmd.Parameters.Add("#sheetname", SqlDbType.NVarChar, 100).Value = sheetName;
DataTable dt = new DataTable();
dt.TableName = sheetName;
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
da.Fill(dt);
ds.Tables.Add(dt);
}
This will generate a dynamic query that will safely escape the name of the table.

How to insert a datatable to an access database in C#

I have 2 table in an access database
now I want to select from one table and insert them into another one.
this is my code but it shows an exception in line Cmd.ExecuteNonQuery();
{"Syntax error (missing operator) in query expression 'System.Object[]'."}
the code is :
public static void SetSelectedFeedIntoDB(Form2 frm2)
{
string StrCon = System.Configuration.ConfigurationManager.ConnectionStrings["FeedLibraryConnectionString"].ConnectionString;
OleDbConnection Connection = new OleDbConnection(StrCon);
OleDbDataAdapter DataA = new OleDbDataAdapter("Select * from FeedLibrary where ID=" + frm2.FeedSelectListBox.SelectedValue, Connection);
DataTable DTable = new DataTable();
DataA.Fill(DTable);
OleDbCommand Cmd = new OleDbCommand();
Cmd.Connection = Connection;
Connection.Open();
foreach (DataRow DR in DTable.Rows)
{
Cmd.CommandText = "insert into SelectedFeeds Values(" + DR.ItemArray + ")";
Cmd.ExecuteNonQuery();
}
Connection.Close();
}
what should I do to fix this?
Your error is caused by the fact that you are concatenating the ItemArray property of a DataRow to a string. In this case the ItemArray (that is an instance of an object[]) has no method that automatically produces a string from its values and thus returns the class name as a string "object[]" but of course this produces the meaningless sql string
"insert into SelectedFeeds Values(object[])";
But you could simply build a SELECT .... INTO statement that will do everything for you without using DataTables and Adapters
string cmdText = #"SELECT FeedLibrary.* INTO [SelectedFeeds]
FROM FeedLibrary
where ID=#id";
using(OleDbConnection Connection = new OleDbConnection(StrCon))
using(OleDbCommand cmd = new OleDbCommand(cmdText, Connection))
{
Connection.Open();
cmd.Parameters.Add("#id", OleDbType.Integer).Value = Convert.ToInt32( frm2.FeedSelectListBox.SelectedValue);
cmd.ExecuteNonQuery();
}
However, the SELECT ... INTO statement creates the target table but gives error if the target table already exists. To solve this problem we need to discover if the target exists. If it doesn't exist we use the first SELECT ... INTO query, otherwise we use a INSERT INTO ..... SELECT
// First query, this creates the target SelectedFeeds but fail if it exists
string createText = #"SELECT FeedLibrary.* INTO [SelectedFeeds]
FROM FeedLibrary
where ID=#id";
// Second query, it appends to SelectedFeeds but it should exists
string appendText = #"INSERT INTO SelectedFeeds
SELECT * FROM FeedLibrary
WHERE FeedLibrary.ID=#id";
using(OleDbConnection Connection = new OleDbConnection(StrCon))
using(OleDbCommand cmd = new OleDbCommand("", Connection))
{
Connection.Open();
// Get info about the SelectedFeeds table....
var schema = Connection.GetSchema("Tables",
new string[] { null, null, "SelectedFeeds", null});
// Choose which command to execute....
cmd.CommandText = schema.Rows.Count > 0 ? appendText : createText;
// Parameter #id is the same for both queries
cmd.Parameters.Add("#id", OleDbType.Integer).Value = Convert.ToInt32( frm2.FeedSelectListBox.SelectedValue);
cmd.ExecuteNonQuery();
}
Here we have two different queries, the first one create the SelectedFeeds table as before, the second one appends into that table.
To discover if the target table has already been created I call Connection.GetSchema to retrieve a datatable (schema) where there is a row if the table SelectedFeeds exists or no row if there is no such table.
At this point I set the OleDbCommand with the correct statement to execute.

fatal error encountered during execution... during update

This code is placed in the button. and when i click it to update the data, a messagebox error appears saying "fatal error encountered during command execution".
Your answers would be a great help. Thank you
MySqlConnection connection = new MySqlConnection(MyConnectionString);
MySqlCommand cmd;
try
{
connection.Open();
cmd = connection.CreateCommand();
cmd.CommandText = "UPDATE student_offense SET TYPE=#TYPE,DATE_HAPPENED=#DH,DESCRIPTION=#DESC,SANCTION=#SANC" +
"Where STUDENT_NO = #STUDENT_NO And DESCRIPTION=#DESC And SANCTION=#SANC And DATE_HAPPENED=#DH";
cmd.Parameters.AddWithValue("#TYPE", offense_combo.Text);
cmd.Parameters.AddWithValue("#DH", date_hapen.Text);
cmd.Parameters.AddWithValue("#DESC", description_txt.Text);
cmd.Parameters.AddWithValue("#SANC", sanction_txt.Text);
cmd.Parameters.AddWithValue("#STUDENT_NO", studentNo_txt.Text);
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
MessageBox.Show("updated");
//refresh
cmd.CommandText = "SELECT student_info.Student_no,student_info.Lastname,student_info.Firstname,student_offense.Type,student_offense.Description,student_offense.Date_Happened,student_offense.Sanction,student_offense.Date_Recorded from student_info,student_offense where student_info.student_no = student_offense.student_no";
MySqlDataAdapter sda = new MySqlDataAdapter();
sda.SelectCommand = cmd;
dbdataset = new DataTable();
sda.Fill(dbdataset);
bSource = new BindingSource();
bSource.DataSource = dbdataset;
dataGridView1.DataSource = bSource;
sda.Update(dbdataset);
bSource.DataSource = dbdataset;
dataGridView1.DataSource = bSource;
student_no_valid.Visible = false;
stud_no_error.Visible = true;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
listBox1.Items.Clear();
description_txt.Text = "";
studentNo_txt.Text = "";
offense_combo.Text = "";
current_date();
sanction_txt.Text = "";
You are missing space between Parameter #SANC and Where .
Try This:
cmd.CommandText = "UPDATE student_offense SET TYPE=#TYPE,DATE_HAPPENED=#DH,
DESCRIPTION=#DESC,SANCTION=#SANC" + " Where STUDENT_NO = #STUDENT_NO And
DESCRIPTION=#DESC And SANCTION=#SANC And DATE_HAPPENED=#DH";
Suggestion : if your DATE_HAPPENED column type is Date in your table,then You need to send the proper Date format.
Try This: Assuming user enters Date in dd-MM-yyyy format.
DateTime dt = DateTime.ParseExact(date_hapen.Text,"dd-MM-yyyy",
CutureInfo.InvariantCulture);
Now while assigning the DATE_HAPPENED value provide the following format
cmd.Parameters.AddWithValue("#DH",dt.ToString("yyyy-MM-dd"));
Probably this happened at cmd.ExecuteNonQuery(); or in the subsequent query. You can verify this by single-stepping through after a breakpoint. There is probably an error in the SQL. You can find this by looking at the internal error, or by trying the query on MySQL Workbench. Check to see that all of the parameters match table columns, and all the data types match.
Incidentally, there is no need to assign SANCTION and DATE_HAPPENED in the update statement since you required them to be equal in the WHERE.

how can i put # in select sql statement?

I have to use the "#"(I don't know it's name). I can use it in update delete or insert statements but I cannot use it in there it gives URL MUST BE DECLARED
//SQL string to count the amount of rows within the OSDE_Users table
string sql = "SELECT * FROM RSSFeeds where URL = #URL";
SqlCommand cmd = new SqlCommand(sql, Connect());
cmd.Parameters.Add("#URL", SqlDbType.VarChar, 500).Value = url;
closeConnection();
SqlDataAdapter adapt = new SqlDataAdapter(sql, Connect());
DataSet ds = new DataSet();
adapt.Fill(ds);
// result of query filled into datasource
adapt.Dispose();
closeConnection();
return ds;
I can only suppose that this line is not correct:
cmd.Parameters.Add("#URL", SqlDbType.Int).Value = url;
Probably URL is not an Int but a NVarChar or other character type
If this is the case then change your line in this way
(255 is the supposed length of your field URL)
cmd.Parameters.Add("#URL", SqlDbType.NVarChar, 255).Value = url;
And, by the way, '#' is called "Parameter Prefix"
EDIT: Seeing the last edit from the OP I update my answer to show what I think is the correct way to go.
//SQL string to count the amount of rows within the OSDE_Users table
string sql = "SELECT * FROM RSSFeeds where URL = #URL";
DataSet ds = new DataSet();
using(SqlConnection cnn = Connect())
using(SqlCommand cmd = new SqlCommand(sql, cnn))
{
cmd.Parameters.Add("#URL", SqlDbType.VarChar, 500).Value = url;
using(SqlDataAdapter adapt = new SqlDataAdapter(cmd))
{
adapt.Fill(ds);
}
}
return ds;
What I have changed:
Encapsulated every disposable object inside an using statement that
is guaranteed to close/dispose objects
Called Connect() just one time and captured the SqlConnection returned to
reuse without creating another one
Created the SqlDataAdapter using the SqlCommand created before (so
the #URL parameter reaches the Sql)
The OP used a closeConnection() and we don't see the internal of this method, but I think that using is enough to close and dispose the connection.
EDIT: The line that creates SqlDataAdapter should be
using(SqlDataAdapter adapt = new SqlDataAdapter(cmd))
cmd.Parameters.AddWithValue("#URL", url);
should work

Sqlite error (DataGrid)

I do not know how to fix the Problem.
It's a sqlite query that should give the requested data record in the DataGrid.
When I enter numbers, it works!
But not when i enter letter's.
SQLite error no such column: Example
My Code :
SQLiteConnection connection = new SQLiteConnection();
connection = new SQLiteConnection("Data Source=Database.s3db;Version=3;New=False;Compress=True;");
SQLiteCommand command = new SQLiteCommand(connection);
SQLiteDataAdapter DB;
DataSet DS = new DataSet();
DataTable DT = new DataTable();
connection.Open();
command = connection.CreateCommand();
string CommandText = "select Example from Lists where Example =" + textBox.Text ;
DB = new SQLiteDataAdapter(CommandText, connection);
DS.Reset();
DB.Fill(DS);
DT = DS.Tables[0];
Grid.DataSource = DT;
connection.Close();
If you are sure that Example exist in your table Lists and its type is of char, nvarchar or other character type then wrap your TextBox.Text in single quote like this
select Example from Lists where Example ='" + textBox.Text +"'" ;
However, try always to use parameter in your query.

Categories