I have a C# WPF desktop application which uses SQL Compact 3.5 as its embedded database.
In the insertion function it has
using (SqlCeCommand com = new SqlCeCommand(
"INSERT INTO FooTable VALUES(#num)", con))
{
com.Parameters.AddWithValue("#num", num);
com.ExecuteNonQuery();
}
I don't get what the com.Parameters.AddWithValue() is about. I commented out this line of code and the insertion function run exactly the same. I thought ExecuteNonQuery carries out the insertion, so what is this Parameters.AddWithValue thing?
#num is a TSQL parameter. Without AddWithValue(#num, num) this is neither defined nor assigned a value. It simply will not work with the parameter omitted, and even if it did: where would it get your chosen value (num) from? The absolute best it could do would be to use null which was not your intent; more typically it would simply fail to execute (are you sure you aren't swallowing an exception somewhere?).
Note that concatenating the value into the string itself is not recommended; it would cause a SQL injection risk, and can reduce performance (plan re-use; not sure this applies to CE though - CE might very well not bother with cached plans).
Related
Being new to C# and postgresql, but not to development and DBs, I'm trying to make the connection from C# .NET to postgresql. I keep running into the same syntax error.
In postgresql I have created a table "Test" with one column "Text".
To insert data into the table, in pgAdmin 4, I use:
insert into public."Test" ("Text") values('It Works!')
This works.
Now I try this in C# where I have a working connection to the database:
1 NpgsqlCommand cmd = new NpgsqlCommand("insert into Test ("Text") values('It Works!')", postconn);
2 cmd.ExecuteNonQuery();
This gives me a compilation error. Apparently from all the double quotes.
If I change the command text to:
"insert into Test ('Text') values('It Works!')"
with single quotes around Text the compiler is happy, but Npgsql gives me a syntax error.
Questions:
In pqsql:
I can see from google that it's possible to get around use the double quotes and the schema reference in psql.
But what does it take?
In C#:
Is there a way to construct the string, so that the compiler will accept it?
pgAdmin 4 is version 1.0
PostgreSQL is version 9.6
C# I believe is the most recent version.
In addition to the comment about escaping your quotes, you really should use parameters instead of literals. It may seem like more work initially, but it's:
Safer (SQL-injection proof)
Easier on the database -- supports compile once, execute many
Avoids having crazy SQL statements within C# that have concacts or string.format all over the place
Avoids the need to single quote literal values and omit quotes for numbers, booleans
Strong datatyping means no formatting (dates, for example)
Here is your code with parameters:
NpgsqlCommand cmd = new NpgsqlCommand("insert into Test (\"Text\") " +
" values(:TEST)", postconn);
cmd.Parameters.AddWithValue("TEST", "It Works");
cmd.ExecuteNonQuery();
Seems like I made your life harder, but your example was a trivial one. As you move to complex SQL statements with multiple parameters and different datatypes, you will see the true value.
On a final rant, while there is nothing technically wrong with making case-sensitive field names, it sure does cause nothing but headaches. Yours is a perfect example. Without the double quotes around the field "Test", you wouldn't have had an issue to begin with.
I've inherited an application with a lot of ADO work in it, but the insert/update helper method that was written returns void. We've also been experiencing a lot of issues with data updates/inserts not actually happening. My goal is to update all of them to check rows affected and depending on the results, act accordingly, but for the time being of finding what may be causing the issue, I wanted to log SQL statements that are called against the server and the number of rows affected by the statement.
This is the statement I'm attempting:
SqlCommand com = new SqlCommand(String.Format("'INSERT INTO
SqlUpdateInsertHistory(Statement, AffectedRows) VALUES (''{0}'', {1});'",
statement.Replace("'", "''"), rows), con);
but it seems to constantly break somewhere in the sql that is being passed in (some cases on single quotes, but I imagine there are other characters that could cause it as well.
Is there a safe way to prep a statement string to be inserted?
I just can't rightly propose a solution to this question without totally modifying what you're doing. You're currently wide open to SQL Injection. Even if this is a local application, practice how you want to play.
using (SqlCommand com = new SqlCommand("INSERT INTO SqlUpdateInsertHistory(Statement, AffectedRows) VALUES (#Statement, #AffectedRows)", con))
{
com.Parameters.AddWithValue("#Statement", statement);
com.Parameters.AddWithValue("#AffectedRows", rows);
com.ExecuteNonQuery();
}
Have you tried SQL Server Profiler? It's already been written and logs queries, etc.
Someone else tried this and got a lot of decent answers here.
I am debugging code someone else wrote that calls a lot of stored procedures (sql server 2008 r2) from C# code. The C# code looks like this
SqlCommand sqlCommand = new SqlCommand(strSP, ConnectionOpen());
sqlCommand.CommandType = CommandType.StoredProcedure;
sqlCommand.CommandTimeout = intTimeOut;
//System.Data.SqlClient.SqlParameter[] prmSQL
if (prmSQL != null)
{
while (i < prmSQL.Length)
{
sqlCommand.Parameters.Add(prmSQL[i]);
i = i + 1;
}
}
SqlDataReader sqlReader = sqlCommand.ExecuteReader();
For debugging my stored procedures I really need the string that sql management studio needs which is like
exec sp_name param one, param two (with quotes if needed for strings and dates..)
The sql command object does not provide this string via some property. The only way I know is to run the sql profiler on sql server and grab the string. Unfortunately the DBA's do not like this since they say running the profiler impacts performance. Is there any addin or code snippet you guys use to get the sp exec string from c# code ? Whats the best way to get this string ? Thanks
You could use a tool like mvc-mini-profiler available on NuGet (note: the name is misleading; it isn't limited to MVC). Minor clarification - since it wraps the connection, you would need to use the abstract DbConnection rather than SqlConnection, and then you just tweak the one line of code (probably in a utility class somewhere) that creates your connection, i.e. instead of:
var conn = new SqlConnection(someString);
return conn;
you might use:
var conn = new SqlConnection(someString);
return new StackExchange.Profiling.Data.ProfiledDbConnection(
conn, MiniProfiler.Current);
There's a couple of other steps to enable it (all shown on the site page), but it literally takes 2 minutes to add to an MVC application. The output is that it monitors, in real time, for enabled users (developers etc), all the activity. We use it 24x7 on stackoverflow/stackexchange (meaning: we made very sure it didn't impact performance). A live demo is available on https://data.stackexchange.com/ - just log in, and the profiling data is visible top-left. It automatically presents the data in a form runnable from SSMS, because that is how we often use it - so: it presents parameters as though they were variable declarations / initializations.
It also plays nicely with ORMs such as LINQ-to-SQL and dapper-dot-net (and many others).
Rep is too low (still a noob to StackOverflow)to comment so I'm posting this as an answer. My apologies. However, you might consider looking at SMO. SMO is a .NET object model that can be used to interact with SQL Server. Using SMO you can get a reference to a specific Stored Procedure
and then enumerate it's parameters.
That might help you get started.
In order to construct the EXEC command, you will need to know the parameter names used by the procedure. I believe you can find them by using the GetDbSchemaTable method, whcih will retrieve stored procedure SQL (I have done this using MS-Access/OLEDB and am assuming it works the same for MS-SQL/SqlClient):
using (conn == new OleDb.OleDbConnection(DBConnection)) {
conn.Open();
DataTable DBObject = conn.GetOleDbSchemaTable(OleDb.OleDbSchemaGuid.Procedures, null);
}
The column named "PROCEDURE_DEFINITION" contains the procedure's SQL and hopefully the parameter list.
You may also want to have a look at Obtaining Schema Information from a Database.
HTH
I'm just curious if the IDbCommand.CommandType's value makes a difference in terms of performance?
Basically, I could do either set it as CommandType.Text and pass in a SQL query "EXEC sp_my_stored_procedure ..." as the CommandText. Or, I could set it as CommandType.StoredProcedure and pass in a stored procedure name "my_stored_procedure" as the CommandText.
I'm wondering if there is any performance difference here, or is it just a matter of passing in a query calling the SP vs passing in the name of the SP?
A side note, I realize that it could depend on the driver, but am not sure. So, if that's the case, I'd like to know that as well. Thanks!
Using the CommandType.StoredProcedure is more efficient. The impact would be felt dependent on your app's load.
In my opinion it is also cleaner. I would generally use CommandType.Text if there was a need to build the command at runtime (i.e. SELECT id, name FROM Table WHERE.......).
Hope this helps,
Kevin
I reflected into the Informix object: IfxCommand which has an internal property named AdjustedCommandText. It seems that this method formats the string value to send to the driver based upon the CommandType.
What's interesting is that it either returns one thing for TableDirect or another for StoredProcedure. Or, just the stored text. Now, the StoredProcedure one goes deeper. If there are no command paramters it just returns "EXECUTE PROCEDURE ...", but if there are command parameters involved then it builds the string up starting with "{?=CALL ..." or {CALL ...".
So, I can say as far as Informix is concerned there is no difference except for clarity and cleanliness. As far as other database drivers, I don't haven't looked into them yet.
I been reading a bit about SQL injection and I want to be sure my code is lets say "safe" from it, I was planning on using RegExp validators to check the user input but another post in here suggested only using parametrized querys, well I'm using them but I want to be sure my code is safe, is it?
using ( SqlConnection dataConnection = new SqlConnection(myConnectionString) )
{
using ( SqlCommand dataCommand = dataConnection.CreateCommand() )
{
dataCommand.CommandText = "INSERT INTO Lines (Name, CreationTime) " +
"VALUES (#LineName, #CurrentDateTime)";
dataCommand.Parameters.AddWithValue("#LineName", TextBox2.Text);
dataCommand.Parameters.AddWithValue("#CurrentDateTime", DateTime.Now.ToString());
dataConnection.Open();
//do other DB stuff
I chop the last part to make the post shorter, the rest is just trying and catching exceptions and closing db connection as well as providing user feedback on inserting successful.
Your code is fine, it is protected from injection because the values are passed as parameters not string literals. However, if you are writing this type of data access yourself, have you considered creating SqlParameter objects and explicitly setting the type, size etc, and adding the parameters to the command? AddWithValue will work just fine, but SQL Server will have to determine the type, a little, but unnecessary overhead.
Well, you could always try to inject a SQL statement into the textbox, that will probably give you a quicker, definite answer.
Yes, that's reasonably safe. So long as you don't use "sanitized" variables from a prepared statement to generate dynamic sql later, you're usually ok. The fact that you're using a prepared statement will take care of dealing with escape characters and other simple methods of injection.
I wouldn't forgo any other validation though...