SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandType = CommandType.Text;
cmd = CreateParameterizedQuery();
SqlDataAdapter dap = new SqlDataAdapter();
dap.SelectCommand = cmd;
DataTable tbl = new DataTable();
dap.Fill(tbl);
if (tbl.Rows.Count > 0)
{
grid.DataSource = tbl;
}
The actual SQL Query will produce results in SQL Management Studio. However I am getting 0 Rows of Data. I set a breakpoint at tbl.Rows.Count and I see it's 0 and stepping will skip the necessary code to set the DataSource.
private SqlCommand CreateParameterizedQuery()
{
SqlCommand command = new SqlCommand();
string[] allTheseWords;
if (textBoxAllTheseWords.Text.Length > 0)
{
allTheseWords = textBoxAllTheseWords.Text.Split(' ');
string SQLQuery = "SELECT distinct [databaseName].[dbo].[customerTable].[name], [databaseName].[dbo].[customerTable].[dos], [databaseName].[dbo].[customerTable].[ACC], [databaseName].[dbo].[reportTable].[id], [databaseName].[dbo].[reportTable].[ACC], [databaseName].[dbo].[reportTable].[fullreport] FROM [databaseName].[dbo].[reportTable], [databaseName].[dbo].[customerTable] WHERE ";
int i = 0;
foreach (string word in allTheseWords)
{
var name = "#word" + (i++).ToString();
command.Parameters.AddWithValue(name, "'%" + word + "%'");
SQLQuery = SQLQuery + String.Format(" [databaseName].[dbo].[reportTable].[fullreport] LIKE {0} AND ", name);
}
SQLQuery = SQLQuery + " [databaseName].[dbo].[customerTable].[ACC] = [databaseName].[dbo].[reportTable].[ACC]";
command.CommandText = SQLQuery;
}
return command;
}
I am using WinForm with C# on Windows 8.
The SQLQuery variable contains this data when debugging
SELECT distinct [databaseName].[dbo].[customerTable].[name], [databaseName].[dbo].[customerTable].[dos], [databaseName].[dbo].[customerTable].[ACC], [databaseName].[dbo].[reportTable].[customerID], [databaseName].[dbo].[reportTable].[ACC], [databaseName].[dbo].[reportTable].[fullreport] FROM [databaseName].[dbo].[reportTable], [databaseName].[dbo].[customerTable] WHERE [databaseName].[dbo].[reportTable].[fullreport] LIKE #word0 AND [databaseName].[dbo].[customerTable].[ACC] = [databaseName].[dbo].[reportTable].[ACC]
debugMySQL is a method that spits out the SQL Query with the parameters substituted
public void debugMySQL()
{
string query = command.CommandText;
foreach (SqlParameter p in command.Parameters)
{
query = query.Replace(p.ParameterName, p.Value.ToString());
}
textBox1.Text = query;
}
The output looks like
SELECT distinct [databaseName].[dbo].[customerTable].[name], [databaseName].[dbo].[customerTable].[dos], [databaseName].[dbo].[customerTable].[ACC], [databaseName].[dbo].[reportTable].[id], [databaseName].[dbo].[reportTable].[ACC], [databaseName].[dbo].[reportTable].[fullreport] FROM [databaseName].[dbo].[reportTable], [databaseName].[dbo].[customerTable] WHERE [databaseName].[dbo].[reportTable].[fullreport] LIKE '%single%' AND [databaseName].[dbo].[customerTable].[ACC] = [databaseName].[dbo].[reportTable].[ACC]
You can see parametrized query with its argument value using SQL Profiler.
Related
I've looked at a lot of similar questions on this site and elsewhere but none of them have helped me.
I'm trying to make a database connection with a query but I get the error
System.Data.SqlClient.SqlException: 'Incorrect syntax near '='.'
on 2 different lines of code. I've tried to use spaces in the query around the = but that doesn't help.
Code 1 is:
string connectieString = dbConnection();
SqlConnection connection = new SqlConnection(connectieString);
SqlCommand select = new SqlCommand();
select.Connection = connection;
select.Parameters.Add("#attackCategory", SqlDbType.NChar).Value = attackCategory;
select.Parameters.Add("#taughtOn", SqlDbType.NVarChar).Value = taughtOn;
select.CommandText = "SELECT ID, Name FROM attackCategory = #attackCategory WHERE TaughtOn = #taughtOn";
using (SqlDataAdapter sda = new SqlDataAdapter(select.CommandText, connection))
{
DataTable dt = new DataTable();
sda.Fill(dt);
return dt;
}
The exception is thrown on the sda.Fill(dt); line of code. This code works if no parameters are used in the query:
string cmd = #"select ID, Name from " + attackCategory + " where TaughtOn ='" + taughtOn + "'";
And code 2 is:
string connectieString = dbConnection();
SqlConnection connection = new SqlConnection(connectieString);
SqlCommand select = new SqlCommand();
select.Connection = connection;
select.Parameters.Add("#attackCategory", SqlDbType.NVarChar).Value = attackCategory;
select.Parameters.Add("#ID", SqlDbType.Int).Value = id;
select.CommandText = "SELECT Name FROM attackCategory = #attackCategory WHERE ID = #ID";
connection.Open();
object name = select.ExecuteScalar();
connection.Close();
return name;
The exception fires on the object name = select.ExecuteScalar(); line of code. This code works if 1 parameter is used in the query:
select.Parameters.Add("#ID", SqlDbType.Int).Value = id;
select.CommandText = "SELECT Inhabitants FROM Planet WHERE ID=#ID";
You cannot provide table name has parameter, parameter applies in where clause with columns value.
string cmd = #"select ID, Name from " + attackCategory + " where TaughtOn ='" + taughtOn + "'";
but, we need to simplify to use parameter in this query.
SqlCommand select = new SqlCommand();
select.Connection = connection;
select.Parameters.Add("#taughtOn", SqlDbType.VarChar,50).Value = taughtOn;
string cmd = #"select ID, Name from " + attackCategory + " where TaughtOn =#taughtOn";
select.CommandText = cmd;
In the above tsql query, string concatenation applies and table name is included in the string, which will work.
Edit:-
I get it why you the sqlDataAdapter is not Recognizing the parameter.
Reason is you have not provided it. Yes, That's right you have provided the CommandText and not the Command Object which is of select variable.
I have corrected your code.
select.Parameters.Add("#taughtOn", SqlDbType.VarChar, 50).Value = taughtOn;
string cmd = #"select ID, Name from " + attackCategory + " where TaughtOn =#taughtOn";
select.CommandText = cmd;
select.Connection = new SqlConnection("provide your sql string");
using (SqlDataAdapter sda = new SqlDataAdapter(select))
{
DataTable dt = new DataTable();
sda.Fill(dt);
return dt;
}
Hope this helps !!
You can't bind object names like that. For object names, you'll have to resort to some sort of string concatenation. E.g.:
select.Parameters.Add("#taughtOn", SqlDbType.NVarChar).Value = taughtOn;
select.CommandText = "SELECT ID, Name FROM " + attackCategory + " WHERE TaughtOn=#taughtOn";
Note:
This is an over-simplified solution that does nothing to mitigate the risk of SQL-Injection attacks. You'll need to sanitize attackCategory before using it like this.
How to use query1 column Display Group into query 2 in the below c# code.
I have denoted the place where i want to put query1 column by ???? symbol.
public class PopulateRangeInStore
{
[Test]
[Category(TestType.NeedsDeployment)]
public void PopulateRangeInStores()
{
ExecutePopulateRangeInStoreProcedure("csg_sp_populate_RangeInStore");
using (var connection = IKBDatabaseConnection.GetConnectionForIKBTFS())
{
string query1 = "SELECT count (distinct DESC7) FROM ix_spc_planogram (NOLOCK) WHERE dbstatus= 1";
string query2 = "SELECT count (distinct EquipmentType) FROM Csg_Range_In_Store (NOLOCK) WHERE DisplayGroup = '" + ?????+ "'";
var command1 = new SqlCommand(query1, connection);
var command2 = new SqlCommand(query2, connection);
//string output = " ";
//var = " ";
//var actualDG = " ";
var actualDG = " ";
var expectedDG = " ";
var dataReader1 = command1.ExecuteReader();
var dataReader2 = command2.ExecuteReader();
if (dataReader1.Read())
{
DataTable dt = new DataTable();
dt.Load(dataReader1);
expectedDG = dt.Rows.Count.ToString();
}
if (dataReader2.Read())
{
DataTable dt = new DataTable();
dt.Load(dataReader2);
actualDG = dt.Rows.Count.ToString();
}
actualDG.Should().Be(expectedDG);
}
}
private void ExecutePopulateRangeInStoreProcedure(string storedProcedure)
{
using (var connection = IKBDatabaseConnection.GetConnectionForIKBTFS())
{
using (SqlCommand cmd = new SqlCommand(storedProcedure, connection))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#ix_sys_error", SqlDbType.Int).Value = 0;
cmd.CommandTimeout = 0;
cmd.ExecuteNonQuery();
}
}
}
}
You can solve it by creating a subquery in the place of ???
string query2 = "SELECT count (distinct EquipmentType) FROM Csg_Range_In_Store (NOLOCK) WHERE DisplayGroup in (" + query2 +")";
I have written to append functions that insert data from custom c# list into MSAccess.
The first simply sets up a new connection for each individual recordset:
public static void appenddatatotable(string connectionstring, string tablename, string[] values)
{
var myconn = new OleDbConnection(connectionstring);
var cmd = new OleDbCommand();
cmd.CommandText = "INSERT INTO " + tablename + " ([RunDate],[ReportingGroup], [Tariff], [Year]) VALUES(#RunDate, #ReportingGroup, #Tariff, #Year)";
cmd.Parameters.AddRange(new[] { new OleDbParameter("#RunDate", values[0]), new OleDbParameter("#ReportingGroup", values[1]), new OleDbParameter("#Tariff", values[2]), new OleDbParameter("#Year", values[3])});
cmd.Connection = myconn;
myconn.Open();
cmd.ExecuteNonQuery();
myconn.Close();
}
I then simply loop over my list of values and call this function on each iteration. This works fine but is slow.
In the second function I tried to include the loop in the function and work with BeginTransction and Committransaction:
public static void appenddatatotable2(string connectionstring, string tablename, string datstr, List<PowRes> values)
{
var myconn = new OleDbConnection(connectionstring);
int icounter = 0;
var cmd = new OleDbCommand();
OleDbTransaction trans = null;
cmd.Connection = myconn;
myconn.Open();
foreach (var item in values)
{
if (icounter == 0)
{
trans = cmd.Connection.BeginTransaction();
cmd.Transaction = trans;
}
cmd.CommandText = "INSERT INTO " + tablename + " ([RunDate],[ReportingGroup], [Tariff], [Year]) VALUES(#RunDate, #ReportingGroup, #Tariff, #Year)";
if (string.IsNullOrEmpty(item.yr))
item.yr = "";
cmd.Parameters.AddRange(new[] { new OleDbParameter("#RunDate", datstr), new OleDbParameter("#ReportingGroup", item.RG), new OleDbParameter("#Tariff", item.tar), new OleDbParameter("#Year", item.yr)});
cmd.ExecuteNonQuery();
icounter++;
if (icounter >= 500)
{
trans.Commit();
icounter = 0;
}
}
if (icounter > 0)
{
trans.Commit();
}
myconn.Close();
}
This also works fine but is EVEN slower.
Is my code wrong? How could I speed up the multiple inserts?
Thanks!
did not test, just my guess for your second function: you add too many parameters to the same command over the loop - cmd.Parameters were never cleared before each usage..
normally committing large set of commands within one connection is much faster than doing them one by one at single connection.
another way to speed up your inserts is to dump all your insert statements into a long text, separated with semicolon, and then fire a commit in one go (i am not sure whether msAccess supports it or not)
EDIT:
to combine the update command into one text:
var updates = values.Select(x => string.Format("INSERT INTO myTable ([RunDate],[ReportingGroup], [Tariff], [Year]) VALUES({0}, {1}, {2}, {3})",
datstr, x.RG, x.tar, x.yr))
.Aggregate((m, n) => m + ";" + n);
cmd.CommandText = update;
Though this could have sql injection issues.
this should be significantly faster than all of your exiting versions
public static void appenddatatotable2(string connectionstring, string tablename, string datstr, List<PowRes> values)
{
string commandText = "INSERT INTO " + tablename + " ([RunDate],[ReportingGroup], [Tariff], [Year]) VALUES(#RunDate, #ReportingGroup, #Tariff, #Year)";
using (var myconn = new OleDbConnection(connectionstring))
{
myconn.Open();
using (var cmd = new OleDbCommand())
{
foreach (var item in values)
{
cmd.CommandText = commandText;
cmd.Parameters.Clear();
cmd.Parameters.AddRange(new[] { new OleDbParameter("#RunDate", datstr), new OleDbParameter("#ReportingGroup", item.RG), new OleDbParameter("#Tariff", item.tar), new OleDbParameter("#Year", item.yr) });
cmd.Connection = myconn;
cmd.Prepare();
cmd.ExecuteNonQuery();
}
}
}
}
I ran the SQL Query in SQL Server Management Studio and it worked.
I get the following error in my WinForm C# application
The parameterized query '(#word1 text)SELECT distinct [database].[dbo].[tableName].[n' expects the parameter '#word1', which was not supplied.
Here is my code
private void buttonRunQuery_Click(object sender, EventArgs e)
{
if (connection == null)
{
connection = ConnectionStateToSQLServer();
SqlCommand command = new SqlCommand(null, connection);
command = createSQLQuery(command);
GetData(command);
}
else
{
SqlCommand command = new SqlCommand(null, connection);
command = createSQLQuery(command);
GetData(command);
}
}
private SqlCommand createSQLQuery(SqlCommand command)
{
string[] allTheseWords;
if (textBoxAllTheseWords.Text.Length > 0)
{
allTheseWords = textBoxAllTheseWords.Text.Split(' ');
string SQLQuery = "SELECT distinct [database].[dbo].[customerTable].[name], [database].[dbo].[customerTable].[dos], [database].[dbo].[customerTable].[accountID], [database].[dbo].[reportTable].[customerID], [database].[dbo].[reportTable].[accountID], [database].[dbo].[reportTable].[fullreport] FROM [database].[dbo].[reportTable], [database].[dbo].[customerTable] WHERE ";
int i = 1;
foreach (string word in allTheseWords)
{
var name = "#word" + (i++).ToString();
command.Parameters.Add(name, SqlDbType.Text);
//(name, SqlDbType.Text).Value = word;
SQLQuery = SQLQuery + String.Format(" [database].[dbo].[reportTable].[fullreport] LIKE {0} AND ", name);
}
SQLQuery = SQLQuery + " [database].[dbo].[customerTable].[accountID] = [database].[dbo].[reportTable].[accountID]";
command.CommandText = SQLQuery;
}
MessageBox.Show(command.CommandText.ToString());
return command;
}
public DataTable GetData(SqlCommand cmd)
{
//SqlConnection con = new SqlConnection(connString);
//SqlCommand cmd = new SqlCommand(sqlcmdString, cn);
SqlDataAdapter da = new SqlDataAdapter(cmd);
connection.Open();
DataTable dt = new DataTable();
da.Fill(dt);
connection.Close();
return dt;
}
The error is happening on da.Fill(dt)
Any suggestions would be helpful
Thank you
In your example, you have commented out the line where you set the value of the Parameter:
command.Parameters.Add(name, SqlDbType.Text);
//(name, SqlDbType.Text).Value = word;
If you do not set a value for a parameter, it is ignored (and won't exist).
Change to this:
command.Parameters.AddWithValue(name, word);
For clarity, consider this quote:
The value to be added. Use DBNull.Value instead of null, to indicate a null value.
From here: SqlParameterCollection.AddWithValue Method
On var name = "#word" + (i++).ToString(); use just i, increment somewhere else.
How can I get elements from table using wildcard?
I've made code something like that.
What is wron here? Is it safe if I put this into loop ?
private void Pokaz()
{
String sql = "SELECT [element] FROM [table] LIKE #Word";
SQLiteConnection connection = new SQLiteConnection(#"Data Source=C:\Temp2\dictionary.s3db");
connection.Open();
SQLiteCommand cmd = new SQLiteCommand(connection);
cmd.CommandText = sql;
cmd.Parameters.AddWithValue("#Word", "%" + "dog" + "%");
DataTable dt = new DataTable();
SQLiteDataReader reader = cmd.ExecuteReader();
dt.Load(reader);
reader.Close();
connection.Close();
dataGridView1.DataSource = dt;
}
I changed to String sql = "SELECT [element] FROM [table] where [element] LIKE \'#Word\'";
But now I get empty result.
I tried also this method. Fixed and works. Still above not.
List<string> list = new List<string>();
string connectionString = #"Data Source=C:\Temp2\dictionary.s3db";
string sql = "SELECT [element] FROM [table] where [element] LIKE \'%dog%\' ";
using (var connection = new SQLiteConnection(connectionString))
{
using (var command = new SQLiteCommand(sql, connection))
{
connection.Open();
SQLiteDataReader rd = command.ExecuteReader();
while (rd.Read())
{
list.Add(rd[0].ToString());
}
}
}
Have you tried
String insSQL = "SELECT [element] FROM [table] like #Word"; //% search with prefix and postfix
SQLiteCommand cmd = new SQLiteCommand(insSQL);
cmd.Parameters.AddWithValue("#Word", "%" + "dog" + "%");
?