What to use in this SqlDataAdapter? - c#

I have a SqlDataAdapter that looks something like:
("Select prodID, CatalogType, prodName, catID, Integration, ItemProfileCatalogID From ShoppingCart t1
INNER JOIN ItemCatalogProfile t2 ON t1.CatalogType = t2.CatalogType
WHERE SessionID = '" + Session["ID"] + "' AND CatalogID ='" + Session["Customer"] ....)
there are a few more included in the where statement, but the one I cannot seem to get to work is:
ItemProfileCatalogID ..
I need to include this to narrow down the items down to only one of each and this variable will do just that if I can figure out what to use in this statement.
I've tried
viewstate[""]
Request.QuerryString[""]
Session[""]
and I cant seem to get those to work..
The problem I am having is, the current shopping cart if I do not have this item to filter, it will return every instance of that particular product in the database because there are up to 250 listings of one item for different catalogs, and that is where the ItemProfileCatalogID comes in, that will filter it down to just the one item
Any suggestions?
Thank you

CatalogID is probably numeric and you are using it as a string in your SQL statement.
It could also be that you have some syntax error in your SQL statement not easily detectable with all the string concatenation going on or due to CatalogID containing a naughty character (' for example)
Also, please check out parametrized queries; concatenation when building SQL statements is usually not a very good idea (SQL injection).

As InBetween said it probably is an issue with it being numeric, you should be able to use the .toString() method to solve this.
Also Stored procedures are generaly more advisable to use for a number of reasons, in your case you mentioned you are working with a shopping cart which suggests maybe some kind of ecommerce application? Using a stored procedure here will mean that SQL does not have to compile your select statement every time you run it thus improving performance and having the code in a stored proc will also increase maintainability and possibly allow you to reuse the procedure in other places.
Added to this you are not actually transmitting the select statement over the network which increases security as no one can intercept this and gain insight into your table structures, and as InBetween mentioned above a stored procedure will help you protect against injection attacks or just simply unforseen data as you can add error handling more easily.

Related

Best practices for inline SQL queries

I'm working with an asp.net website that uses a lot of inline SQL queries... and I'm wondering if it is best to create the inline queries on the fly:
int i = 500;
using (SqlConnection conn = new SqlConnection(connStr))
{
SqlCommand com = new SqlCommand(conn);
...
com.CommandText = "select from table where column < #parameter";
...
}
Or to have a class to hold all queries needed for the application. Something like this:
class SqlQueries
{
private string query1 =
"select * from tblEmployees where EmployeeName = #EmployeeName";
private string query2 =
"select * from tblVacation where EmployeeName = #EmployeeName";
public string Query(string s)
{
string str = string.Empty;
switch (s)
{
case "query1":
str = query1;
break;
case "query2":
str = query2;
break;
}
return str;
}
}
Thank you!
I've used a lot of ADO.NET queries in my day and I have always used the first method. The second method is an interesting idea, but it might be cumbersome to edit those queries if you are at another place in the code that uses it. It also makes it harder to see what a query is doing at a particular place in code. Example:
string sql = "Update User set age = #age where UserId = #UserId";
tells a developer what is happening, while:
string sql = SqlQueries.Query("updateAge");
Leaves questions about what table/columns are being updated. Also, with the first one, you know exactly what params need to be added.
If you are writing this query in several places that might change things
It's not terrible to put the literal directly in the method, as long as you always call that same method every time you want to run that query. However, if you are going to copy that string literal into multiple places in your code, then a constant is definitely preferred. However, rather than taking a string as the argument for the Query method in your second example, it should take an enumeration value.
However, if you are using the second method you described, I would ask you why you don't just start using stored procedures instead?
I would recommend using stored procedures as a much better solution to your problem than hard coded in-line queries. If you have to change the query at a later date, you don't have to rebuild your application, so bugs in your query can be fixed without needing to deploy the whole application. The 2nd option you have there is a maintenance nightmare waiting to happen. It all looks so nice when you have one or two queries in it, but that begins to look a bit more ugly when you have tens or hundreds in there. Your code looks like it's c#, so I would recommend checking out the Microsoft Enterprise Library,
http://msdn.microsoft.com/en-us/library/ff632023.aspx
You might need to download a different version depending on what version of the .NET framework you are developing with.
If you absolutely have to have "inline" sql as opposed to stored procedures (and I have done this for utility type applications that merely interact with a database, rather than own it), I would suggest putting your SQL into an embedded resource file. This will make your queries easier to maintain (although you will still need to re-compile your app to make changes).
I think it's OK to have the queries "inline" as long as they aren't repeated in several places. If that starts to happen, then you might want to start creating Query classes.
In both the cases you are ultimately building/fetching String which you will pass to CommandText. So there would be no such difference. Only thing you need to consider in your case is how you would maintain the code or how will other people understand your code.
If you're going to use inline SQL at least don't put it in the web page code because it will be painful when you make database changes to know what it affects. Putting all the queries in one classes might be a bit disorganized, but if you grouped them by functional classes (like manager classes for your business objects) it might be easier to deal with.
If your queries are longer than a line or two, you should consider putting them in their own .sql file. Set the build action on the file to embedded resource, and access it with a call to GetManifestResourceStream(). That way, you're elevating your sql to the status of a proper language, with syntax highlighting, validation and intellisense (when you connect VS to your DB). Needless to say, this hugely facilitates maintenance.
If all this seems like a hassle, grab my VS extension, QueryFirst. Create your .sql files with the provided template and they will automatically be wired up for compilation. But you won't care because you'll just access the queries via the generated classes.
Sql is the only computer language I can think of that we accept to see chopped up in string literals. It ought to be a scandal.

Escaping various characters in C# SQL from a variable

I'm working a C# form application that ties into an access database. Part of this database is outside of my control, specifically a part that contains strings with ", ), and other such characters. Needless to say, this is mucking up some queries as I need to use that column to select other pieces of data. This is just a desktop form application and the issue lies in an exporter function, so there's no concern over SQL injection or other such things. How do I tell this thing to ignore quotes and such in a query when I'm using a variable that may contain them and match that to what is stored in the Access database?
Well, an example would be that I've extracted several columns from a single row. One of them might be something like:
large (3-1/16" dia)
You get the idea. The quotes are breaking the query. I'm currently using OleDb to dig into the database and didn't have an issue until now. I'd rather not gut what I've currently done if it can be helped, at least not until I'm ready for a proper refactor.
This is actually not as big problem as you may see it: just do NOT handle SQL queries by building them as plain strings. Use SqlCommand class and use query parameters. This way, the SQL engine will escape everything properly for you, because it will know what is the code to be read directly, and what is the parameter's value to be escaped.
You are trying to protect against a SQL Inject attack; see https://www.owasp.org/index.php/SQL_Injection.
The easiest way to prevent these attacks is to use query parameters; http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlparameter.aspx
var cmd = new SqlCommand("select * from someTable where id = #id");
cmd.Parameters.Add("#id", SqlDbType.Int).Value = theID;
At least for single quotes, adding another quote seems to work: '' becomes '.
Even though injection shouldn't be an issue, I would still look into using parameters. They are the simpler option at the end of the day as they avoid a number of unforeseen problems, injection being only one of them.
So as I read your question, you are building up a query as a string in C#, concatenating already queried column values, and the resulting string is either ceasing to be a string in C#, or it won't match stuff in the access db.
If the problem is in C#, I guess you'll need some sort of escaping function like
stringvar += escaped(columnvalue)
...
private static void escaped(string cv) as string {
//code to put \ in front of problem characters in cv
}
If the problem is in access, then
' escapes '
" escapes "
& you can put a column value containing " inside of '...' and it should work.
However my real thought is that, the SQL you're trying to run might be better restructured to use subqueries to get the matched value(s) and then you're simply comparing column name with column name.
If you post some more information re exactly what the query you're producing is, and some hint of the table structures, I'll try and help further - or someone else is bound to be able to give you something constructive (though you may need to adjust it per Jet SQL syntax)

Is it efficient to use SQL functions on the left-hand side of SELECT commands?

I'm designing a C# program using .NET and Windows Forms. At one point I need to open a form that contains a DataGridView object and a TextBox. The DataGridView object is to be fed with the input on the TextBox and show real-time matches from the database.
To accomplish this, I've been using the simple SQL Query that follows:
SqlCommand cmd = "SELECT name,document_no FROM clients WHERE LEFT(name, " + textboxname.Text.Len + ") = '" textboxname.Text + "'";
It works for now, while my database contains about a dozen of rows, but is it efficient for large-sized (2k+ entries) databases?
The approach you're taking won't be efficient - at least, not if there's an index on the name column (if there is no such index then expect poor performance whatever you do). Typically, any function called in a WHERE clause where one or more of the parameters are columns is going to defeat any attempts of the query optimizer to use indexes on those columns.
Much better is:
SELECT name,document_no FROM clients WHERE name LIKE 'yourtextboxtexthere%'
...which will have a good chance of using the index on name.
2k+ entries, yeah, you are probably OK. 2M+ entries and I'd say that you are not OK. the LEFT function probably won't use an index. Consider using the "WHERE name LIKE " + txtboxname.Text + "%" instead.
problems to consider.
Sql injection, you should either
sanitize the txtboxname.Text or use
parameterized queries.
Indexes usually are used with the LIKE statement as long as the
'%' is at the begining or the end of
the statement and not both (ala
'%sometext%')

Execute query only if it is select statement. How?

string sqlQuery = "unknown";
I need to write a function which receives a sql query as parameter e.g. sqlQuery. I would like to execute it only if it is select statement and return data. In other case, if parameter sqlQuery contains delete, update or truncate, the function should return null.
I wonder if there is way to achieve this without parsing contents of parameter sqlQuery.
I would like to do this using c sharp for oracle queries.
Any tips. Thanks.
Update:
This should work for all kinds of users with all privileges.
Run the query in the context of a user who only has select privileges. Any other type of query will error out.
SET TRANSACTION READ ONLY, then execute the string. If it attempts to modify data, it will generate an ORA-01456 error. You can trap this and return whatever you want.
If you really have to work with a constructed string that will operate on the database, you should use the DBMS_ASSERT database package to make sure you have a pure query that's not subject to SQL injection. There's a nice paper on the Oracle site about that here.
The basics are:
only give the minimum privileges necessary, for example only giving the user "select" as described in an earlier reply. And then only on the minimum necessary set of tables. Views are really helpful here in limiting access.
Use bind variables where that's possible.
If you can't use bind variables then check the purity of your statement using DBMS_ASSERT
You can probably search the string for keywords like "update", "delete", "truncate" and all the other ways you can do ddl or dml on the table, but it is very error-prone. You have to eliminate strings in the query which might have these keywords and there are a lot of keywords that you have to take into account.
If your requirement is to return null, Why not give just the select privilege on the necessary objects and return null if you encounter the Insufficient Privileges error?
http://download.oracle.com/docs/cd/E11882_01/server.112/e17069/strms_trapply.htm#STRMS1065
I would not allow the client to specify a SQL select string. Too many possible attack vectors.
Have you considered using Linq? The caller could pass a Func<T, bool> that could be passed to a Where clause. Since Linq will generate the select statement for you, there's no possibility of a non-select statement occuring.
Bear in mind a SELECT column FROM table FOR UPDATE will still take an exclusive lock on every row on that table. And it only needs SELECT privileges (none of INSERT, UPDATE or DELETE are required).
You can use ADO.NET SqlCommand http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.aspx. It has methods ExecuteReader for a select type query and ExecuteNonQuery for other sql expression, you jest set the CommandText string attribute. If I'm right it throws exception if the query is not a select in ExecuteReader but you must check it.
string sqlQuery = "("+evil_sql+")";
Only a subquery can start with a parentheses. This will stop DML, DDL, and the FOR UPDATE issue that Gary mentioned. You still have to execute everything, just catch all the errors. I've done this on a public-facing website without any issues.
Even if your user is not directly granted anything you'll need to check for unnecessary PUBLIC grants. And of course keep your system patched. There have been exploits in functions that can be called in a SELECT.

Optimal code - One large query but more complicated data retrieval or lots of small queries

I have a C# program that retrieves multiple rows from a DB but currently does them one at a time on the same connection.
Would it be better to write it so that instead of repeatedly running (where blah changes each time):
select data from table where name = 'blah'
To something like:
select name, data from table where name in ('blah','blah2','blah3')
I'm nervous of making this change as I am unsure of the additional overhead of retrieving this data from the resulting table.
Please note the example data is not representative of the actual data so I can't do anything like:
select name, data from table where name like 'blah%'
Additionally this is in a highly stressed environment so even the slightest improvement could be significantly beneficial.
Thanks in advance,
Tom
I'd go for one chunky request. At least from a performance point of view this is the better approach.
One trip to the DB is mutch more efficient than multiple small hits.
I would expect the use of single statement to yield better performance and you will decrease the overhead associated with statement preparation, submission, and execution. However, as with any optimisation - you should try it and measure it before committing to it.
You might also want to look at preparing and submitting a batch of statements instead of making individual requests. Also, for the first case, check that you are preparing the statement once and caching the prepared statement - saving you overhead on the repeated compilation of the statement.
Theorically, one single query is better. Even if the processing time at the database is the same, you save resources and time by avoiding the multiple roundtrip communications between the database server and the client.
That said, this is one type of problem that calls for profiling to actually measure the improvements of any changes made.
A parameterized query is both fast and secure. It caches query plans and protects against SQL injection.
SELECT name, data
FROM table
WHERE name in (#name1, #name2, #name3)
In the calling code you can add parameters as needed. For example (C#):
var command = connection.CreateCommand();
command.CommandText = "SELECT name, data FROM table WHERE name in (";
int index = 0;
string separator = "";
foreach (string value in valueList)
{
string paramName = "#p" + Convert.ToString(index);
command.CommandText += separator + paramName;
command.Parameters.Add(paramName, value);
separator = ", ";
index++;
}
command.CommandText += ")";
I'd go for one operation calling
select data from table... etc.etc.
via a stored procedure: that will then let you tinker with the SQL logic (possible optimizations) without having to alter anything in your frontend code.
One statement is best, and optimise through the database..

Categories