2

What is the best way to evaluate a SQL statement in C# to determine if it does more than just select? - Ie- check if values would be changed (insert, update, delete, modify, or drop) if the statement was later executed.

Any ideas as far as out of the box C# dlls/functions i can use, or is this something I should code myself using string-parsing techniques?

Thanks.

Brian Rasmussen
  • 114,645
  • 34
  • 221
  • 317
Chris
  • 968
  • 16
  • 27
  • 1
    What is the use-case? Are you evaluating user-entered ad-hoc queries (that could be malicious), or implementing something internal to an application? – mellamokb Dec 12 '11 at 20:25
  • http://stackoverflow.com/questions/589096/parsing-sql-code-in-c-sharp ? – Marc Gravell Dec 12 '11 at 20:29
  • The user will input the query, and then my code will execute the query (if it is determined to be non-malicious, and does not modify the data source). – Chris Dec 12 '11 at 20:31
  • How about letting the user enter a LINQ expression instead? – Alex Dec 12 '11 at 22:39

2 Answers2

12

I would use db permissions. Create a database user with read-access only and then, any queries that do anything other than SELECT will fail.

James Hull
  • 3,669
  • 2
  • 27
  • 36
  • 3
    small caveat - even a `SELECT` can cripple a server... a cross join or 7 should be enough... – Marc Gravell Dec 12 '11 at 20:40
  • Well - that's the trade off he is going to have to make if he wants to safely check if the query is going to alter data. Trying to parse the SQL will create a world of problems and is just waiting for an injection attack. – James Hull Dec 12 '11 at 20:41
  • @MarcGravell - yea and I do not see how it can be predicted by anything you would do with the query text – mfeingold Dec 12 '11 at 20:42
  • 4
    I don't disagree - I only mention so that the OP is aware of the context – Marc Gravell Dec 12 '11 at 20:45
  • lolz @Bigfellahull did you decided to down vote me coz I said best answer is in comments by Marc ? – Surjit Samra Dec 12 '11 at 23:06
1

One method would be to use a transaction and then rollback, with obvious limitations (may not work on complex queries, like ones returning multiple result sets with other updates in between, and will not work on queries that use non-rollback commands like DBCC - may want to catch exceptions as well for situations like those):

using(SqlConnection sqlConn = new sqlConnection(CONNECTION_STRING))
{
    sqlConn.Open();
    using (SqlTransaction trans = sqlConn.BeginTransaction())
    {
        // execute code and see if rows are affected here
        var query = " ... " ;
        var cmd = new SqlCommand(query, sqlConn);
        var rowsAffected = cmd.ExecuteNonQuery();
        if (rowsAffected > 0) { ... }

        // roll back the transaction
        trans.RollBack();
    }
    sqlConn.Close();
}
mellamokb
  • 56,094
  • 12
  • 110
  • 136